Timus 1577
简单DP;
状态转移方程如下:
令len[i][j]表示串1前i个字符与串2前j个字符所得到的符合要求的串的最短长度。
令res[i][j]表示串1前i个字符与串2前j个字符所得到的符合要求的最短串的方案数。
len[i][j] = str1[i]==str2[j] ? len[i-1][j-1] +1: min(len[i-1][j],len[i][j-1])+1。
若str1[i]==str2[j],res[i][j]=res[i-1][j-1];
若 str1[i]!=str2[j] ,分三种情况:
(1)len[i-1][j] < len[i][j-1] , res[i][j]=res[i-1][j];
(2)len[i-1][j] > len[i][j-1], res[i][j]=res[i][j-1];
(3)len[i-1][j]==len[i][j-1], res[i][j]=res[i][j-1]+res[i-1][j];
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAX 1000000007 char str1[2010],str2[2010]; int res[2][2010][2]; int work(int n,int m) { int i,j,e=0; for(i=0;i<=m;i++) { res[e][i][0]=i; res[e][i][1]=1; } for(i=1;i<=n;i++) { e=1-e; res[e][0][0]=i; res[e][0][1]=1; for(j=1;j<=m;j++) { if(str1[i]==str2[j]) { res[e][j][0]=res[1-e][j-1][0]+1; res[e][j][1]=res[1-e][j-1][1]; continue; } if(res[e][j-1][0] < res[1-e][j][0]) { res[e][j][0]=res[e][j-1][0]+1; res[e][j][1]=res[e][j-1][1]; } if(res[e][j-1][0] > res[1-e][j][0]) { res[e][j][0]=res[1-e][j][0]+1; res[e][j][1]=res[1-e][j][1]; } if(res[e][j-1][0] == res[1-e][j][0]) { res[e][j][0]=res[e][j-1][0]+1; res[e][j][1]=(res[e][j-1][1]+res[1-e][j][1])%MAX; } } } return res[e][m][1]; } int main() { while(scanf("%s %s",str1+1,str2+1)!=EOF) { printf("%d\n",work(strlen(str1+1),strlen(str2+1))); } return 0; }