题目:
题目描述
一个字符串A的子串被定义成从A中顺次选出若干个字符构成的串。如A=“cdaad" ,顺次选1,3,5个字符就构成子串" cad" ,现给定两个字符串,求它们的最长共公子串。
输入
第一行两个字符串用空格分开。两个串的长度均小于2000 。
输出
最长子串的长度。
样例输入 Copy
abccd aecd
样例输出 Copy
3
解析:
创建一个dp数组,dp[i][j]表示当数组a长度为i,数组b长度为j时的最长字段长度。
这样,随着i和j的增加,会出现两种情况:
如果a[i]=b[j],这样在dp[i-1][j-1]的基础上,会多出一对相同的字符a[i]和b[j],此时dp[i][j]=dp[i-1][j-1]+1。
如果a[i]不等于b[j],没有新的相同字符出现,这时候dp[i][j]=dp[i-1][j]或者dp[i][j]=dp[i][j-1],只需判断两者谁大就行:dp[i][j] = max(dp[i-1][j],dp[i][j-1])
由此得出dp方程:
代码:
#include<iostream>
using namespace std;
const int N = 2005;
string a,b;
int dp[N][N];
int main()
{
cin>>a>>b;
int x = a.size(),y = b.size();
//初始化
for(int i=0;i<=x;i++)
dp[i][0] = 0;
for(int j=0;j<=y;j++)
dp[0][j] = 0;
//dp方程
for(int i=1;i<=x;i++)
{
for(int j=1;j<=y;j++)
{
if(a[i-1]==b[j-1])//因为我的a,b数组是从下标0开始存的,而这两层循环的i,j是从1开始的,所以需要减去1
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
cout<<dp[x][y];
}