给定一个序列X=<x1,x2,x3,x4…,xm>,另一个序列Z=<z1,z2,z3,z4…,zk>,若存在一个严格递增的X的下标序列<i1,i2,i3,…,ik>对所有的1,2,3,…,k,都满足x(ik)=zk,则称Z是X的子序列。
比如Z=<B,C,D,B>是X=<A,B,C,B,D,A,B>的子序列。
求最长公共子序列。
Sample Input:
abcfbc abfcab
programming contest
abcd mnp
Sample Output:
4
2
0
方法一:朴素递归
#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
const int Max = 1000 + 10;
char s1[Max], s2[Max];
int Fun(int n, int m){
if(n == 0 || m == 0)
return 0;
else{
if(s1[n] == s2[m])
return Fun(n-1, m-1) + 1;
else
return max(Fun(n-1, m), Fun(n, m-1));
}
}
int main(){
while(scanf("%s%s", s1 + 1, s2 + 1)){
int n = strlen(s1 + 1);
int m = strlen(s2 + 1);
int answer = Fun(n, m);
cout << answer << endl;
}
system("pause");
return 0;
}
方法二:递归策略+记忆法
#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
const int Max = 1000 + 10;
char s1[Max], s2[Max];
int memo[Max][Max];
int Fun(int n, int m){
if(memo[n][m] != -1)
return memo[n][m];
int answer;
if(n == 0 || m == 0)
answer = 0;
else{
if(s1[n] == s2[m])
answer = Fun(n-1, m-1) + 1;
else
answer = max(Fun(n-1, m), Fun(n, m-1));
}
memo[n][m] = answer;
return answer;
}
int main(){
while(scanf("%s%s", s1 + 1, s2 + 1)){
int n = strlen(s1 + 1);
int m = strlen(s2 + 1);
for(int i = 0; i <= n; i++)
for(int j = 0; j <= m; j++)
memo[i][j] = -1;
int answer = Fun(n, m);
printf("%d\n", answer);
}
system("pause");
return 0;
}
方法三:递推方程
#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
const int Max = 1000 + 10;
char s1[Max], s2[Max];
int dp[Max][Max];
void Fun(int n, int m){
for(int i = 0; i <= n; i++){
for(int j = 0; j <= m; j++){
if(i == 0 || j == 0)
dp[i][j] = 0;
else{
if(s1[i] == s2[j])
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = max(dp[i-1][j] , dp[i][j-1]);
}
}
}
}
int main(){
while(scanf("%s%s", s1 + 1, s2 + 1)){
int n = strlen(s1 + 1);
int m = strlen(s2 + 1);
for(int i = 0; i <= n; i++)
for(int j = 0; j <= m; j++)
dp[i][j] = -1;
Fun(n, m);
int answer = dp[n][m];
printf("%d\n", answer);
}
system("pause");
return 0;
}