杭电Common Subsequence(1159):
题意:
求两个字符串的最大公共子串。
Sample:
abcfbc abfcab
programming contest
abcd mnp
4
2
0
代码:
#include<iostream>
#include<string.h>
using namespace std;
const int MAX = 1000 + 10;
char a[MAX];
char b[MAX];
int DP[MAX][MAX];
int Max(int x, int y){ //求最大值
return x > y ? x : y;
}
int main(){
while(cin>>a>>b){
int len1 = strlen(a);
int len2 = strlen(b);
memset(DP,0,sizeof(DP)); //初始为0,dp问题必备
// DP[i][j]表示s1前i个字符与s2的前i个字符的最长公共字串长度
for(int i=1; i<=len1; i++){
for(int j=1; j<=len2; j++){
if(a[i-1] == b[j-1])
DP[i][j] = DP[i-1][j-1]+1; //相等时最大长度加1
else
DP[i][j] = Max(DP[i-1][j], DP[i][j-1]); //不相等时取前面的最大值
}
}
cout<<DP[len1][len2]<<endl;
}
return 0;
}
滚动数组Common Subsequence
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 1000 + 10;
int Max (int a, int b){
return a > b ? a : b;
}
char a[maxn];
char b[maxn];
int DP[2][maxn]; //相当用两行的的一维数组,因为每次dp的转换只以前一行相关,所以其它的行可以重新用
int main(){
while(cin>>a>>b){
int len1 = strlen (a);
int len2 = strlen (b);
memset(DP, 0, sizeof(DP));
for(int i=1; i<=len1; i++){
for(int j=0; j<=len2; j++){
if(a[i-1]==b[j-1])
DP[i%2][j]=DP[(i-1)%2][j-1]+1;
else
DP[i%2][j]=Max(DP[(i-1)%2][j],DP[i%2][j-1]);
}
}
cout<<DP[len1%2][len2]<<endl;
}
return 0;
}
(扩展)用公共子串求最大回文串:
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 5000 +10;
int dp[2][maxn];
int Max(int a, int b){
return a > b ? a : b;
}
int main(){
int n;
while(cin>>n){
getchar();
char s1[maxn];
char s2[maxn];
gets(s1);
int len1 = strlen(s1);
for(int i=0; i<len1; i++){
s2[len1 - i - 1] = s1[i];
}
memset (dp, 0, sizeof(dp));
for(int i=1;i<=n;i++){
for(int j=0;j<=n;j++){
if(s1[i-1]==s2[j-1]){
dp[i%2][j]=dp[(i-1)%2][j-1]+1;
}
else{
dp[i%2][j]=Max(dp[(i-1)%2][j],dp[i%2][j-1]);
}
}
}
//cout<<dp[n%2][n]<<endl;
cout<<n - dp[n%2][n]<<endl; //总长度减去最大回文串的值就为最大公共串值
}
return 0;
}