这道题是动态规划的典型题目。
动态方程:
if(str1[i] == str2[j])
MaxLen[i][j] = MaxLen[i-1][j-1] + 1;//比较到两个字母相同时,把前一状态的值加1就得到当前的最长公共序列
else
MaxLen[i][j] = max(MaxLen[i][j-1], MaxLen[i-1][j]);//比较到两个字母不同时,分别将两个字符串后移一个字符,比较两种情况哪个得到的公共子序列最长
思路:把str1和str2分别比较它们的前i,j的字符串的公共序列,把求最大分解为求每个子序列的最大公共序列,然后用数组存储它们的解,自下而上,求出Maxlen[1][1],就能求出Maxlen[2][2],一直到Maxlen[i][j],从而提高效率。应该说是一种优化的穷举法。
动态规划算法是这样的:
先求出Maxlen[1][1]一直到Maxlen[1][j],然后就可以求出Maxlen[2][1]一直到Maxlen[2][j],一直到最后就能得到Maxlen[i][j].得到一个矩阵,Maxlen[len1][len2]就是问题的解。
#include <iostream>
#define MAX_LEN 201
using namespace std;
char str1[MAX_LEN];
char str2[MAX_LEN];
int MaxLen[MAX_LEN][MAX_LEN];
int main()
{
while (scanf("%s%s", str1+1, str2+1) != EOF) //scacnf读取字符串时不要加&,因为数组名本身就是地址.并且没有输入时scanf会返回EOF
{
int Len1 = strlen(str1 + 1);
int Len2 = strlen(str2 + 1);
int i, j;
for(i = 0; i <= Len1; i++)
MaxLen[i][0] = 0; //注意初始化边界条件,Maxlen[i][0]表示str1[i]与str2[0]的公共序列,显然是0
for(j = 0; j <= Len2; j++)
MaxLen[0][j] = 0;
for(i = 1; i <= Len1; i++)
{
for(j = 1; j <= Len2; j++)
if(str1[i] == str2[j])
MaxLen[i][j] = MaxLen[i-1][j-1] + 1; //比较到两个字母相同时,把前一状态的值加1就得到当前的最长公共序列
else
MaxLen[i][j] = max(MaxLen[i][j-1], MaxLen[i-1][j]); //比较到两个字母不同时,分别将两个字符串后移一个字符,比较两种情况哪个得到的公共子序列最长
}
printf("%d\n", MaxLen[Len1][Len2]);
}
return 0;
}