2 a b aa ab
1 2
注:DP d(i, j)表示最长公共子串长度 f(i, j)表示长度为d(i,j)的子串存在于Y中的数目
递推公式:很简单,选择一个条件,然后分析情况
这里选择取不取X(i)
I. if d(i, j) == d(i-1, j) then f(i, j) += f(i-1, j);
II.if d(i, j) == d(i-1, p-1) + 1 | X(i)==Y(p) && p<=j then f(i, j) += f(i-1, p-1).
Node: Initial Conditions--d(0,i) = d(i, 0) = 0, f(0, i) = f(0, i) = 1, f(i, j) = 0;
<pre name="code" class="cpp">#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define maxn 1005 #define MOD 1000000007 char s1[maxn], s2[maxn]; int d[maxn][maxn]; int f[maxn][maxn]; int pos[maxn][27]; void solve() { int len1 = strlen(s1+1); int len2 = strlen(s2+1); memset(f, 0, sizeof(f)); for(int i=0; i<=len2; i++) { d[0][i] = d[i][0] = 0; f[0][i] = f[i][0] = 1; } for(int i=1; i<=len1; i++) for(int j=1; j<=len2; j++) if(s1[i] == s2[j]) d[i][j] = d[i-1][j-1] + 1; else d[i][j] = max(d[i-1][j], d[i][j-1]); memset(pos, 0, sizeof(pos)); for(int i=1; i<=len2; i++) { for(int j=0; j<26; j++) pos[i][j] = pos[i-1][j]; pos[i][s2[i]-'a'] = i; } f[0][0] = 1; for(int i=1; i<=len1; i++) for(int j=1; j<=len2; j++) { if(d[i][j] == 0) { f[i][j] = 1; continue; } if(d[i][j] == d[i-1][j]) f[i][j] = (f[i][j] + f[i-1][j]) % MOD; int p = pos[j][s1[i]-'a']; if(p && d[i][j] == d[i-1][p-1] + 1) f[i][j] = (f[i][j] + f[i-1][p-1]) % MOD; } printf("%d\n", f[len1][len2]); } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int T; cin>>T; while(T--) { scanf("%s", s1+1); scanf("%s", s2+1); solve(); } return 0; }