`
yihuijie2011
  • 浏览: 8537 次
社区版块
存档分类
最新评论

最大公共子串算法

阅读更多

     有两种思想,就像珠宝商放在天鹅绒上的宝石一样熠熠生辉。一个是微积分,另一个就是算法。微积分以及在微积分基础上建立起的数学分析体系造就了现代科学,而算法造就了现代世界。

                                                                                                          ——David Berlinski

最大公共子串问题JavaScript版

求最大公共子串,常见的做法是使用矩阵。假设有字符串:abcdefg和字符串abcd,则可构成如下矩阵。

1     a    b    c    d    e    f    g
2 a   1    0    0    0    0    0    0
3 b   0    1    0    0    0    0    0
4 c   0    0    1    0    0    0    0
5 d   0    0    0    1    0    0    0

对两个字符串的每一项都进行比较,若匹配则该项为1,不匹配则为0。然后求出对角线最长为1的那一段序列,即为最大公共子串。看上面的分开,似乎得使用二维数组了,在两个字符串都较大的情况下不是很划算,是否可以进一步优化?

可以,需要改变一下策略,如果该项匹配,则该项的值为再设为1,而是其对角线a[i-1, j-1](i > 1 && j > 1)的值+1,这样便可以只使用一个一维数组。

以一个字符串作为“行”,另一个作为“列”,比较两个字符串各项的值,用另外一个变量记录数组的最大值和字符串的起始位置。代码如下:

01 function LCS(str1, str2) {
02   
03     if (str1 === "" || str2 === "") {
04         return "";
05     }
06   
07     var len1 = str1.length;
08     var len2 = str2.length;
09       
10     var a = new Array(len1);
11     var maxLen = 0;
12     var maxPos = 0;
13       
14     for (var i = 0; i < len1; i++) { //行
15         for (var j = len2 - 1; j >= 0; j--) {//列 
16             if (str1.charAt(j) == str2.charAt(i)) {
17                 if (i === 0 || j === 0) {
18                     a[j] = 1;
19                 } else {
20                     a[j] = a[j - 1] + 1;
21                 }
22             } else {
23                 a[j] = 0;
24             }
25   
26             if (a[j] > maxLen) {
27                 maxLen = a[j];
28                 maxPos = j;
29             }
30         }
31     }
32   
33     return str1.substr(maxPos - maxLen + 1, maxLen);
34 }

但代码其实并不是最优的,为什么?因为上面的写法必须等待两层循环都完成。有没有相对更快一些的方法呢?

设有字符串a、b,其长度分别为len1、len2,其公共字子串一定是 <= Math.min(len1, len2),而且子串必定连续,且一定是a、b的子串。

01 function findMaxSubStr(s1,s2){ 
02     var str= "",
03         L1=s1.length,
04         L2=s2.length; 
05       
06     if (L1>L2){ 
07         var s3=s1;
08         s1=s2;
09         s2=s3;
10         s3 = null;
11         L1=s2.length;
12         L2 = s1.length;
13     }
14       
15       
16     for (var i=L1; i > 0; i--) {
17         for (var j= 0; j <= L2 - i && j < L1; j++){ 
18             str = s1.substr(j, i);
19             if (s2.indexOf(str) >= 0) {
20                 return str; 
21             }
22         
23     }
24       
25     return ""
26 }

先比较s1、s2的长度,然后取较短的字符串作为。substr(idex, len),所以拿较短的串取其子串,然后判断它是否在较长的字符串中存在,如果存中则直接返回,否则再取下一位。

完整示例:

001 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
002 <html xmlns="http://www.w3.org/1999/xhtml">
003  <head>
004   <title>www.nowamagic.net</title>
005   <style type='text/css'>
006     body {background-color:#fff;}
007   </style>
008  </head>
009   
010  <body>
011 <script type='text/javascript'>
012 function LCS(str1, str2) {
013   
014     if (str1 === "" || str2 === "") {
015         return "";
016     }
017   
018     var len1 = str1.length;
019     var len2 = str2.length;
020       
021     var a = new Array(len1);
022     var maxLen = 0;
023     var maxPos = 0;
024       
025     for (var i = 0; i < len1; i++) { //行
026         for (var j = len2 - 1; j >= 0; j--) {//列 
027             if (str1.charAt(j) == str2.charAt(i)) {
028                 if (i === 0 || j === 0) {
029                     a[j] = 1;
030                 } else {
031                     a[j] = a[j - 1] + 1;
032                 }
033             } else {
034                 a[j] = 0;
035             }
036   
037             if (a[j] > maxLen) {
038                 maxLen = a[j];
039                 maxPos = j;
040             }
041         }
042     }
043   
044     return str1.substr(maxPos - maxLen + 1, maxLen);
045 }
046   
047   
048 function findMaxSubStr(s1,s2){ 
049     var str= "",
050     L1=s1.length,
051     L2=s2.length; 
052       
053     if (L1>L2) { 
054     var s3=s1;
055     s1=s2;
056     s2=s3;
057     s3 = null;
058     L1=s2.length;
059     L2 = s1.length;
060     }
061       
062       
063     for (var i=L1; i > 0; i--) {
064     for (var j= 0; j <= L2 - i && j < L1; j++){ 
065             str = s1.substr(j, i);
066             if (s2.indexOf(str) >= 0) {
067         return str; 
068         }
069        
070     }
071       
072     return ""
073
074   
075   
076     !(function() {
077     var tmpArr = [];
078     for (var i = 97; i < 97 + 26; i++) {
079         tmpArr.push(String.fromCharCode(i));
080     }
081       
082     var s2 = tmpArr.join("");
083   
084     tmpArr.sort(function() {return Math.random() > 0.7;});
085     var s1 = new Array(600).join(tmpArr.join(""));
086       
087       
088     var date = getNow();
089     alert(  "消耗时间:" + (getNow() - date) + "秒  " + LCS(s1, s2));
090   
091     date = getNow();
092     alert(  "消耗时间:" + (getNow() - date) + "秒  " + findMaxSubStr(s1, s2) );
093    })();
094   
095 function getNow() {
096     return new Date().getTime();
097 }
098 </script>
099  </body>
100 </html>

正文转载于http://www.nowamagic.net/algorithm/algorithm_LargestCommonSubstring.php

0
0
分享到:
评论
1 楼 暴风雪 2012-03-18  
膜拜效率是O(n^2)的算法……为什么不用后缀树/后缀数组优化到O(logn)呢?

相关推荐

    最大公共子串计算论文相似度源程序

    最大公共子串计算论文相似度:事件复杂度O(m*n),空间复杂度Omin(m,n)),可以用来计算两个字符串的最大公共子串长度、相似度;可以用于论文相似度量、地理信息等基于相似度量的查询等环境。由于空间复杂度低,因此可...

    动态规划实现两序列最大公共子串查找(Python代码)

    最大公共子串问题是IT行业的经典面试题之一,在生物信息等领域也有重要应用。该资源使用动态规划实现了最大公共子串查找算法,问题具体描述在Problem里,代码为code.py,调试结果请参考Readme。

    LCS(longest common substring)算法,即最大公共子串 C实现

    LCS(longest common substring)算法,即最大公共子串,它是求两个字符串最长公共子串的问题。大体解法是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长...

    java实现字符串匹配求两个字符串的最大公共子串

    主要介绍了java实现求两个字符串最大公共子串的方法,详细的描述了两个字符串的最大公共子串算法的实现,需要的朋友可以参考下

    最长公共子串MFC实现

    MFC实现数据结构的简单问题,最长公共子串,界面良好,算法简单

    面试必考字符串相关的动态规划——最大公共子序列、最大公共子串、编辑距离

    字符串相关的动态规划最大公共子序列最大公共子串编辑距离 简述这三个算法解决的问题和展示状态转移方程并且给出可通过执行的Python代码。 最大公共子序列 子序列是,一个字符串中的任意字符组成的序列,重点在于,...

    我用Python写的一些算法

    使用动态规划的两种方式实现的LCS(最大公共串)(下面的算法都会使用动态规划的两种方式来实现) 加权有向无环图中最短路径和最长路径 背包问题 最长回文子串(lps) ###幂乘:算法复杂度是O(lgn) ##贪心算法 活动...

    ACM算法模板和pku代码

    枚举+kmp判定,最长公共子串 铺砖,KMP好题 后缀数组,最长公共子串 后缀数组,最长不相交子串 后缀数组,取出字典序最小的序列 后缀数组,分三段,分别倒转,字典序最小 AC自动机实现多串匹配

    《数据结构与算法》c语言实现代码

    《数据结构》c语言实现的完整程序代码。 ------找两个字符串的最大公共子串代码

    利用C语言来求最大连续子序列乘积的方法

    也就是说:最长公共子串(Longest CommonSubstring)和最长公共子序列(LongestCommon Subsequence,LCS)的区别:  子串(Substring)是串的一个连续的部分,子序列(Subsequence)则是从不改变序列的

    Java学习指南,涵盖大部分Java程序员所需要掌握的核心知识

    最大公共子串 动态规划 大厂面试爱问的「调度算法」,20 张图一举拿下 图解红黑树 面试必备 | 不可不会的反转链表 红黑树【图解】 算法学习工具网站 必会框架 Spring全家桶以及源码分析 SpringCloud 分布式框架基石-...

    ACM 内部预定函数

    4.LCS—最大公共子串长度 5.LCS-生成最大公共子串 6.数字转化为字符 计算几何: 1.叉乘法求任意多边形面积 2.求三角形面积 3.两矢量间角度 4.两点距离(2D、3D) 5.射向法判断点是否在多边形内部 6.判断点...

    最新笔试面试常用算法收集打包

    2009/09/26 19:59 3,215 最长公共子串.txt 2009/10/01 18:52 540,464 最长重复子串问题.mht 2009/10/03 16:28 86,677 最长重复字串 搜索墙.mht 2009/12/24 13:14 &lt;DIR&gt; 百度算法 2009/09/27 15:08 114,176 笔试题...

    【Java面试+Java学习指南】一部分大部分Java招聘所需要掌握的核心知识

    目录(善用Ctrl+F) 本人面试点合集 脑图在线编辑地址 ...最大公共子串 动态规划 大厂面试爱问的「调度算法」,20张图一举拿下 图解红黑树 面试必备 | 不可能的食品链表 红黑树【图解】 改进学习工具网站 必会框架

    程序员编程艺术:面试和算法心得.pdf

    • 第五章 动态规划 o 5.0 本章导读 o 5.1 最大连续乘积子串 o 5.2 字符串编辑距离 o o o 5.3 格子取数 5.4 交替字符串 5.10 本章习题 第三部分 综合演练 • 第六章 海量数据处理 o 6.0 本章导读 o 6.1 关联式...

    高效算法:竞赛、应试与提高必修128例.[法] Christoph Dürr Jill-Jênn Vie(带书签文字版).pdf

    2 8 字符串的最长回文子串:Manacher 算法 42 第 3 章 序列 44 3 1 网格中的最短路径 44 3 2 编辑距离(列文斯登距离45 3 3 最长公共子序列 47 3 4 升序最长子序列 49 3 5 两位玩家游戏中的必胜策略 52 第 4 章 数组...

    ACM算法模板选doc

    n最长公共子串 Prim最小生成树 Kruskal最小生成树 Dijkstra最短路径 Bellman-Ford 卡塔兰数 组合序列 整点三角形 BFS最长路径 树状数组 背包 凸包面积 高精度除法取模 完全匹配KM 字符串KMP 凸包graham算法 输出最短...

    1_金策_字符串算法选讲.pdf

    在 O(n log n) 时间空间预处理后(或较复杂的 O(n) 时间空间 预处理), 可以 O(1) 回答: 两个子串的最长公共前缀 (LCP)、最 长公共后缀 (LCS)。 对于拥有周期 p 的串 s, LCP(s[1..n], s[1 + p..n]) = n − p。 输入 ...

    node-sift-distance:SIFT距离算法

    筛选 4 通过安装 $ npm install sift-distance 注意:此模块的主要版本跟踪算法的版本。 因此,如果您想使用 SIFT 3,例如,您需要安装sift-distance@3.0 ,用于 ... 要相互匹配的最大公共子串偏移量。 默认为5 。 数

    ACM 算法经典代码 数据结构经典代码

    11. 最大子串匹配 121 12. 最大子段和 122 13. 最大子阵和 123 常用源代码 包括很多经典算法 数学问题: 1.精度计算——大数阶乘 2.精度计算——乘法(大数乘小数) 3.精度计算——乘法(大数乘大数) 4.精度...

Global site tag (gtag.js) - Google Analytics