Title Link: BZOJ-5282
Problem analysis
LCS is solved with the classic O (n^2) DP, F[i][j] represents the length of the LCS before the X string and the J character before the Y string.
F[I][J] = max (F[i-1][j], f[i][j-1]);
if (x[i] = = Y[j]) f[i][j] = max (F[i][j], f[i-1][j-1] + 1);
Then set a state G[i][j], which represents the first I character of the X-string, how many sub-sequences of f[i][j] are also sub-sequences of J characters before the Y-string.
And then transfer it in two different situations:
1) sub-sequence not including x[i], if (f[i-1][j] = = F[i][j]) g[i][j] + = g[i-1][j];
2) subsequence containing x[i], if (f[i-1][p-1] + 1 = = F[i][j]) g[i][j] + = g[i-1][p-1]; (P is the most up-to-x[i] position of the first J-character in the Y-string. )
It would be nice to transfer.
When initializing g[][], assign values to g[0][] and g[][0].
Code
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <cmath > #include <algorithm>using namespace std;inline int gmax (int a, int b) {return a > B? a:b;} const int MAXN = + 5, Mod = 1000000007;int T, N, M, Lp;int F[maxn][maxn], G[maxn][maxn];char x[maxn], y[maxn];int mai N () {scanf ("%d", &t); for (int case = 1; Case <= T; ++case) {scanf ("%s%s", X + 1, Y + 1), n = strlen (x + 1), M = strlen (Y + 1), memset (f, 0, sizeof (f)), memset (g, 0, sizeof (g)); fo R (int i = 1; I <= n; ++i) for (int j = 1; j <= m; ++j) {F[i][j] = Gmax (F[i-1][j], f[i][j-1]); if (x[i] = = Y[j]) f[ I][J] = Gmax (F[i][j], f[i-1][j-1] + 1);} G[0][0] = 1;for (int i = 1; I <= n; ++i) g[i][0] = 1;for (int i = 1; I <= m; ++i) g[0][i] = 1;for (int i = 1; i < = N; ++i) {LP = 0;for (int j = 1; j <= m; ++j) {if (y[j] = = X[i]) Lp = j;if (f[i-1][j] = = F[i][j]) {G[i][j] + = G[i-1][j];g I [j]%= Mod;} if (Lp! = 0 && f[i-1][lp-1] + 1 = = f[I][j]) {G[i][j] + = g[i-1][lp-1];g[i][j]%= Mod;}} printf ("%d\n", G[n][m]);} return 0;}
[HDOJ-5282] Senior ' s String "DP"