寻找最长公共子串的问题

问题:现在有两个字符串,我们要寻找它们最长的公共子串。比如regression和express这两个字符串,它们的子串有e和ress,那么它们的最长公共字串就是ress。

解法:

我们利用一个二维数组来记录两个字符串相互匹配的情况,如果字符串str1长度为len1,字符串str2长度为len2,那么数组可以设为table[len1][len2]。

对于数组中的每个元素table[i][j],当字符串对应位置的值一致时(str1[i] == str2[j])为1,不一致时为0。当全部对比完成之后,数组中对角线上连续出现1的次数最多的,就是它们的连续的最长公共子串的长度。

但是由于我们要找的是它们最长公共字串的值,并且要找到对角线上连续出现1的次数也需要新的计算。我们可以改进算法:当字符串对应位置的值一致时(str1[i] == str2[j]),table[i][j] = table[i-1][j-1] + 1。这样,我们就可以方便地得到最长公共子串的长度了。同时我们可以记录table[i][j]最大时,i或者j的序号,就可以得到最长公共子串的位置了。

代码如下:

 1 void lcs(char* str1, char* str2)
 2 {
 3     // get length of the strings
 4     int len1 = strlen(str1);
 5     int len2 = strlen(str2);
 6     // build 2-D array
 7     vector<vector<int> > arr;
 8     arr.resize(len1);
 9     for(int i = 0; i < len1; i++) {
10         arr[i].resize(len2);
11     }
12     // compare
13     int maxLen = 0;
14     int maxIdx = 0;
15     int i;
16     int j;
17     i = 0;
18     for (j = 0; j < len2; j++) {
19         if (str2[j] == str1[i]) {
20             arr[i][j] = 1;
21         }
22     }
23     j = 0;
24     for (i = 0; i < len1; i++) {
25         if (str2[j] == str1[i]) {
26             arr[i][j] = 1;
27         }
28     }
29     for (i = 1; i < len1; i++) {
30         for (j = 1; j < len2; j++) {
31             if (str2[j] == str1[i]) {
32                 arr[i][j] = arr[i-1][j-1] + 1;
33                 if (arr[i][j] > maxLen) {
34                     maxLen = arr[i][j];
35                     maxIdx = i;
36                 }
37             }
38         }
39     }
40     // output lcs
41     char *result = (char *) malloc(maxLen+1);
42     memcpy(result, str1 + maxIdx - maxLen + 1, maxLen);
43     result[maxLen] = ‘\0‘;
44     printf("str1:%s\n", str1);
45     printf("str2:%s\n", str2);
46     printf("result:%s\n", result);
47 }
时间: 2024-08-24 04:51:23

寻找最长公共子串的问题的相关文章

动态规划之最长公共子串

一 问题引入 在生物学中,经常需要比较两个不同生物的DNA,一个DNA串由由一串称为碱基的的分子组成,碱基有鸟嘌呤,腺嘌呤,胞嘧啶,胸腺嘧啶四中,我们用英文字母的首字母表示四种碱基,那么DNA就是在有限集{A,C,G,T}上的一个字符串.例如某种生物的DNA序列为:S1=ACCGGTCGAGTGCGCGGAAGCCGGCCGAA,S2=GTCGTTCGGAATGCCGTTGCTCTGTAAA,我们比较两个DNA串的原因就是希望确定他们的相似度,作为衡量两个物种相似度的标准.如果一个串是另外一个串

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和

参考:http://www.ahathinking.com/archives/124.html 最长公共子序列 1.动态规划解决过程 1)描述一个最长公共子序列 如果序列比较短,可以采用蛮力法枚举出X的所有子序列,然后检查是否是Y的子序列,并记录所发现的最长子序列.如果序列比较长,这种方法需要指数级时间,不切实际. LCS的最优子结构定理:设X={x1,x2,……,xm}和Y={y1,y2,……,yn}为两个序列,并设Z={z1.z2.……,zk}为X和Y的任意一个LCS,则: (1)如果xm=

【实习记】2014-08-29算法学习Boyer-Moore和最长公共子串(LCS)

昨天的问题方案一:寻找hash函数,可行性极低.方案二:载入内存,维护成一个守护进程的服务.难度比较大.方案三:使用前5位来索引,由前3位增至前5位唯一性,理论上是分拆记录扩大100倍,但可以就地利用mysql,最易行.方案四:使用方案三,但增加一个表以减少冗余,但代价新开一个表,并且每次查询都select join两个表. 研究了 求最长公共子串问题,顺便研究了字符串匹配 字符串匹配的Boyer-Moore算法http://www.ruanyifeng.com/blog/2013/05/boy

最长递增子序列 &amp;&amp; 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离

http://www.cppblog.com/mysileng/archive/2012/11/30/195841.html 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列. 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i]. 这样简单的复杂度为O(n^2),其实还有更好的方

利用后缀数组(suffix array)求最长公共子串(longest common substring)

摘要:本文讨论了最长公共子串的的相关算法的时间复杂度,然后在后缀数组的基础上提出了一个时间复杂度为o(n^2*logn),空间复杂度为o(n)的算法.该算法虽然不及动态规划和后缀树算法的复杂度低,但其重要的优势在于可以编码简单,代码易于理解,适合快速实现. 首先,来说明一下,LCS通常指的是公共最长子序列(Longest Common Subsequence,名称来源参见<算法导论>原书第3版p223),而不是公共最长子串(也称为最长公共子串). 最长公共子串问题是在文本串.模式串中寻找共有的

最长公共子串+最长公共子序列

两道题都可以用动态规划的方法做,只是状态转移方程不同. 最长公共子串(注意子串是连续的) 1.先建立一个二维数组array[str1.size()][str2.size()](全部初始化为0),初始化第一行和第一列(元素相同处置1),然后进入状态方程 2.状态转移方程: if(str1[i] == str2[i]) array[i][j]=array[i-1][j-1]+1; (左上方对角线的值加上1) 否则无操作. 3.最后寻找整个array中的最大值即可(因为可能有多个子串) 1 /* 2

算法设计 - LCS 最长公共子序列&amp;&amp;最长公共子串 &amp;&amp;LIS 最长递增子序列

出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的最长公共子串方法.最长公共子串用动态规划可实现O(n^2)的时间复杂度,O(n^2)的空间复杂度:还可以进一步优化,用后缀数组的方法优化成线性时间O(nlogn):空间也可以用其他方法优化成线性.3.LIS(最长递增序列)DP方法可实现O(n^2)的时间复杂度,进一步优化最佳可达到O(nlogn)

最长公共子串

(连续) - 阿里笔试[分析+编码] 题目描述:给定一个query和一个text,均由小写字母组成.要求在text中找出以同样的顺序连续出现在query中的最长连续字母序列的长度.例如,query为“acbac”,text为“acaccbabb”,那么text中的“cba”为最长的连续出现在query中的字母序列,因此,返回结果应该为其长度3.请注意程序效率. [思路]用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0.然后求出对角线最长的1序列,其对应的位置

一天一道算法题(5)---最长公共子串

题目 给定两个字符串str1和str2,返回两个字符串的最长公共子串.例如:str1="1AB2345CD",str2="12345EF",公共子串是"2345" 解析 最长公共子串和最长公共子序列的区别是,子串是连续的,子序列是不连续的. 首先还是要生成动态规划表.生成大小为M*N的矩阵dp.dp[i][j]的含义是,在必须把str1[i]和str2[j]当作公共子串最后一个字符的情况下,公共子串最长能有多长.比如,str1="A12