您的位置:首页 > 其它

LCS 最大公共序列算法粗略讲解

2016-08-09 14:16 337 查看

定义

一个序列,如果是两个或多个已知序列的子序列,且是所有子序列中最长的,则为最长公共子序列。

举个例子,如:有两个随机字符串,123456 和 34589,则它们的最长公共子序列便是:345。

最长公共子串和最长公共子序列的区别

子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。

解法

当数列的量为一定的时,都可以采用动态规划去解决。该算法的空间、时间复杂度均为O(n^2),经过优化后,空间复杂度可为O(n),时间复杂度为O(nlogn)。

字符串str1和str2,长度分别为len1,len2,创建一个dp[len1][len2]的二维数组,初始化dp数组的值全部为0,i和j分别从1开始,i++,j++循环:

如果str1[i-1] == str2[j-1],则dp[i][j] = dp[i- 1, j -1] + 1;

如果str1[i-1] != str2[j-1],则dp[i][j] = max(dp[i][j-1],dp[i-1][j])

比如举个例子:str1字符串为abcfbc,str2字符串为abfcab。下面列个表格

//abfcab
/0000000
a0111111
b0122222
c0122333
f0123333
b0123334
c0123444
而dp[len1][len2]极为最大公共序列长度 例子答案就是4

下面就上代码了。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#include <set>

using namespace std;

#define sc(x,y) scanf("%s %s",x,y)
#define FOR(i,n) for(int i=0;i<n;i++)
#define pr(x) printf("%d\n",x)

const int maxn=1005;
char str1[maxn],str2[maxn];
int dp[maxn][maxn];
int main()
{
while(~sc(str1,str2))
{
int len1=strlen(str1);
int len2=strlen(str2);
memset(dp,0,sizeof(dp));//初始化数组dp
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
if(str1[i-1]==str2[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
}
else
{
dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
}
}
}
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
printf("%d ",dp[i][j]);
}
printf("\n");
}
pr(dp[len1][len2]);
}
return 0;
}


END!!!!!!!!!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: