含义:
给出两个字符串,求出这样的1个最长的公共子序列的长度:子序列中的每个字符都应在原串中找到,且每个字符的先后顺序和原串中的先后顺序一致。
举个栗子:
如(abcfbc 和 abfcab两个串,左边为串s1,右边为串s2,则” abc “为他们当中的一个子序列,且符合上面我所讲的条件。且 “ abcb ”也是当中的一个子序列,字符可以在原串中找到,且先后顺序相同。“ abcb ”是其中一个最长公共子序列。他的长度是4)。
POJ 1458 Common Subsequence:
题目要求:给两个子串s1,s2,求s1和s2的最长公共子序列的长度。
思路:
1.输入两个子串s1,s2,。(字符从0开始输入)
2.用 MaxLen(i , j )表示s1前 i个字符形成的子串与s2前 j 个字符形成的子串的最长公共子序列的长度。(牢记这句话)、
显然,假设s1串长为length1,s2串长length2,则要求的即为MaxLen(length1,length2).
3.讨论MaxLen的大小:
①。显然,maxLen(n,0)=0,(当n = 0,1,2,3...length1时)。同理maxLen(0,n)=0。(当n = 0,1,2,3,...length2时)。
②。其次,当s1[ i-1 ] == s2[ j-1 ]时,maxLen(i , j) = maxLen(i-1,j-1)+1。
【也即s1串的第i-1个字符和s2串的第j-1个字符相同时,他们的最长公共子序列的长度就是原来2个串减1的长度在加上 1,。】(因为串从0开始输入,故i-1是串左边的的第 i 个字符。)
③。再次,当s1[i-1] != s2[ j-1 ]时,maxLen (i,j) = max( maxLen(i,j-1),maxLen(i-1,j) ).
【也即s1串和s2串最后一个字符不相同时,比较maxLen(i,j-1)和maxLen(i-1,j)的最大值。】
【(我举个例子,比如(aeb c和abd s,当比较maxLen(4,4)时,最后一个字符c和最后一个字符s不同,故比较maxLen(3,4)和maxLen(4,3),也即比较2和2的大小。选择他们中的较大者。
4.经过m轮计算,得出结果。即输出最后maxLen(lengh1,length2)
实例解析:
假设我们来分析串“ abcfbc ” 和串“ abfcab ”的最长公共子序列:
1.设两个子串s1,s2.并输入。
//设两个子串s1和s2
char s1[1000];
char s2[1000];
//设置以i到j的最长子串为maxLength[i][j]
int maxLength[1000][1000];
//输入字符串s1,s2
cin >> s1 >> s2;
2.易得,maxLength(n,0) = 0和maxLength(0,n) = 0(n=0,1,2,....),这代表一字符串和空串的最长公共子序列,必定为0.。
for(int i=0;i<=length1;i++)
maxLen[i][0] = 0;
for(int j=0;j<=length2;j++)
maxLen[0][j] = 0;
3.接下来即可开始考虑,maxLen怎么递推。当最后一个字符相同怎么处理,不同怎么处理。
for(int i=1;i<length1;i++)
{
for(int j=1;j<length2;j++)
{
if(s1[i-1]==s1[j-1] //这里可能你会有点迷糊,因为字符是从第0开始的,数字i,j代表前i个后后j个子串,故是从1开始的。
maxLen[i] = maxLen[i-1][j-1] + 1;
else
maxLen[i] = max(maxLen[i-1][j],maxLen[i][j-1]);
}
}
列出一个小图,代表过程。
![](https://i-blog.csdnimg.cn/blog_migrate/ab0db54f869eb72a4cfea4b08b9590c0.png)
时间复杂度分析:O(m*n), m行n列每个maxLen都遍历一遍。
下面列出整个代码:
#include <iostream>
#include <cstring>
using namespace std;
char s1[1000];
char s2[1000];
int maxLength[1000][1000];
int main()
{
while(cin >> s1 >> s2)
{
int length1 = strlen(s1);
int length2 = strlen(s2);
int i,j;
for(i=0;i<=length1;i++)
maxLength[i][0] = 0;
for(j=0;j<=length2;j++)
maxLength[0][j] = 0;
for(i=1;i<=length1;i++)
{
for(j=1;j<=length2;j++)
{
if(s1[i-1]==s2[j-1])
maxLength[i][j] = maxLength[i-1][j-1] + 1;
else
maxLength[i][j] = max(maxLength[i-1][j],maxLength[i][j-1]);
}
}
//test
for(i=0;i<=length1;i++)
{
for(j=0;j<=length2;j++)
cout << maxLength[i][j]<<" ";
cout << endl;
}
cout << endl;
cout << maxLength[length1][length2] << endl;
}
}
注:我还在代码中列出了test部分,他展示了maxLen[i][j]的变化过程,可以验证我们的计算。submit时记得删除。