问题描述:
给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列
比如样例输入:
abcfbc abccab
样例输出
4
分析:1、确定状态: f[i][j]:表示前一个字符的前i位于后一个字符的前j位的最长公共子序列长度
2、确定状态转移方程:
if x[i]==y[j] 长度为i的子序列和长度为j的最长公共子序列就是长度为i-1和长度为j-1的子序列中最长的序列加1,即f[i][j]=f[i-1][j-1]+1
if x[i]!=y[j] —第一个序列长度为i的子序列和第二个序列中长度为j的子序列的公共子序列中x[i]和y[j]不同时出现。
—也就是说在x[0]~x[i]和y[0]~y[i]的最长公共子序列实际上与x[0]~x[i-1]和 y[0]~y[i]的最长公共子序列一样或者与x[0]~x[i]和 y[0]~y[i-1]的最长公共子序列一样
—
即:
f[i][j]=max(f[i - 1][j] ,f[i][j - 1])
举例:
写程序时注意的问题:1.写了好几次都是wrong answer 造成的原因是因为:数组开小了,刚开始开的是200,后来扩大到999
2.while(scanf("%s%s",x,y)!=EOF)注意x,y此时为字符串型
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
char x[999],y[999];
int f[1000][1000];// 很容易出错
int m,n;
while(scanf("%s%s",x,y)!=EOF)
{
m=strlen(x);n=strlen(y);
for(int i=0;i<=m;i++)
{
f[i][0]=0;
}
for(int j=0;j<=n;j++)
{
f[0][j]=0;
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(x[i-1]==y[j-1])
f[i][j]=f[i-1][j-1]+1;
else
f[i][j]=max(f[i-1][j],f[i][j-1]);
}
}
printf("%d\n",f[m][n]);
}
return 0;
}