您的位置:首页 > 其它

LCS(最长连续子序列+最长连续字串)

2017-05-17 21:32 323 查看
最长公共子串(LCS),有三种情况:

1.公共子串的元素必须相邻.

2.公共子串的元素可以不相邻。

3. 求多个字符串的最长公共子串。

第一个,公共子串的元素必须相邻.

解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的位置.

其中,将dp[i][j]的左上角dp[i-1][j-1]设置比它大一(有利于最后统计)。

#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
int main()///求最长公共连续子串
{
int dp[110][110];
string s1="21232523311324";
string s2="312123223445";
char p[110];
int len1=s1.length();
int len2=s2.length();
int st=0,ed=0;
int len=0;
for(int i=0; i<len1; i++)
{
for(int j=0; j<len2; j++)
{
if(s1[i]==s2[j])
{
if(i==0||j==0)
dp[i][j]=1;
else
{
dp[i][j]=dp[i-1][j-1]+1;
}
}
else
{
dp[i][j]=0;
}
if(dp[i][j]>len)
{
len=dp[i][j];
ed=j;
}
}
}
st=ed-len+1;
for(int i=0; i<len1; i++)
{
for(int j=0; j<len2; j++)
{
printf("%d ",dp[i][j]);
}
cout<<endl;
}
printf("公共字串:\n");
for(int i=st; i<=ed; i++)
{
printf("%c",s2[i]);
}
cout<<endl;
return 0;
}


求公共子串的元素可以不相邻问题。

用动态规划法,用二维数组统计两个字串的比较结果。

1、序列s1和序列s2

·长度分别为m和n;

·创建1个二维数组dp[m.n];

·初始化L数组内容为0

·m和n分别从0开始,m++,n++循环:

- 如果s1[m] = s2
,则dp[m,n] = dp[m - 1, n -1] + 1;

- 如果s1[m] != s2
,则dp[m,n] = max{dp[m,n - 1],dp[m - 1, n]}

·最后从L[m,n]中的数字一定是最大的,且这个数字就是最长公共子序列的长度

·从数组L中找出一个最长的公共子序列

2、从数组L中查找一个最长的公共子序列

i和j分别从m,n开始,递减循环直到i = 0,j = 0。其中,m和n分别为两个串的长度。

·如果s1[i] == s2[j],则将str[i]字符插入到子序列内,i–,j–;

·如果s1[i] != s2[j],则比较dp[i,j-1]与dp[i-1,j],dp[i,j-1]大,则j–,否则i–;(如果相等,则任选一个)

#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
int main()///求最长公共连续子序列
{
int dp[100][100];
string s1="ABCBDAB";///找出两者的最长公共不连续序列
string s2="BDCABA";
int len1=s1.length();
int len2=s2.length();
memset(dp,0,sizeof(dp));
for(int i=1; i<=len1; i++)
{
for(int j=1; j<=len2; j++)
{
if(s1[i-1]==s2[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
}
else
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
for(int i=0; i<=len1; i++)
{
for(int j=0; j<=len2; j++)
printf("%d ",dp[i][j]);
cout<<endl;
}

for(int i = len1, j = len2; i >= 1 && j >= 1;)
{
if(s1[i - 1] == s2[j - 1])
{
cout << s1[i - 1] << " ";//倒序打印的
i--;
j--;
}
else
{
//  if(dp[i][j -1] >= dp[i - 1][j])//打印:B A D B
if(dp[i][j -1] > dp[i - 1][j]) //打印:A B C B
{
j--;
}
else
{
i--;
}
}
}
cout << endl;
cout<<dp[len1][len2]<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: