最长公共子序列问题
定义:
最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。而最长公共子串(要求连续)和最长公共子序列是不同的。 最长公共子序列的问题常用于解决字符串的相似度,是一个非常实用的算法。这道题可以用动态规划的思想去解答。
举个例子,cnblogs这个字符串中子序列有多少个呢?很显然有27个,比如其中的cb,cgs等等都是其子序列,我们可以看出
子序列不见得一定是连续的,连续的那是子串。
我想大家已经了解了子序列的概念,那现在可以延伸到两个字符串了,那么大家能够看出:cnblogs和belong的公共子序列吗?
在你找出的公共子序列中,你能找出最长的公共子序列吗?
从图中我们看到了最长公共子序列为blog,仔细想想我们可以发现其实最长公共子序列的个数不是唯一的,可能会有两个以上,
但是长度一定是唯一的,比如这里的最长公共子序列的长度为4。
设有二维数组f[i,j] 表示 X 的 i 位和 Y 的 j 位之前的最长公共子序列的长度,则有:
f[i,j] = 0 i=0或j=0;
f[i,j] = f[i-1,j-1] + 1 i,j>0 X[i] = Y[j];
f[i,j] = max(f[i-1,j],f[i,j-1]) i,j>0 X[i] !=Y[j]。
南阳oj 36题
最长公共子序列
时间限制:3000 ms | 内存限制:65535 KB
难度:3
- 描述
- 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列。
tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。
- 输入
- 第一行给出一个整数N(0<N<100)表示待测数据组数
接下来每组数据两行,分别为待测的两组字符串。每个字符串长度不大于1000. - 输出
- 每组测试数据输出一个整数,表示最长公共子序列长度。每组结果占一行。
- 样例输入
-
2 asdf adfsd 123abc abc123abc
- 样例输出
-
3 6
代码实现:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 #define N 1003 6 char ch1[N],ch2[N]; 7 int a[N][N]; 8 int max(int a,int b) 9 { 10 return a>b?a:b; 11 } 12 int LCS(int n,int m) 13 { 14 int i, j; 15 for(i=0;i<=n;i++) 16 a[i][0] = 0; 17 for(j=0;j<=m;j++) 18 a[0][j] = 0; 19 for(i=1;i<=n;i++) 20 for(j=1;j<=m;j++) 21 { 22 if(ch1[i-1] == ch2[j-1]) 23 a[i][j] = a[i-1][j-1] + 1; 24 else 25 a[i][j] = max(a[i-1][j],a[i][j-1]); 26 } 27 return a[n][m]; 28 } 29 int main() 30 { 31 int n; 32 int count; 33 int len1,len2; 34 cin>>n; 35 getchar(); 36 while(n--) 37 { 38 gets(ch1); 39 gets(ch2); 40 len1 = strlen(ch1); 41 len2 = strlen(ch2); 42 count = LCS(len1,len2); 43 cout<<count<<endl; 44 } 45 return 0; 46 }