2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)
全靠 wxh的博客 补完这套。wxhtxdy!
$f[i][k]$ 表示在第 $i$ 个位置刚好匹配了 $k$ 个字符。转移方程 $$ f[i][k] = \sum_{i - j > h[s[k - 1]]} f[j][k - 1] $$
前缀和优化加滚动就行了。
好像可以直接用 $f[i][k]$ 表示前缀和,就没这么多事了。
#include <bits/stdc++.h> const int N = 1e5 + 7; const int MOD = 1e9 + 7; int dp[2][N], sum[2][N], h[N]; char s[N], t[N]; void M(int &a) { if (a >= MOD) a -= MOD; } int main() { freopen("in.txt", "r", stdin); int k, n; scanf("%d%d", &k, &n); for (int i = 0; i < 26; i++) scanf("%d", h + i); scanf("%s%s", t + 1, s + 1); for (int i = 1; i <= n; i++) { if (s[i] == t[1]) dp[1][i] = 1; sum[1][i] = sum[1][i - 1] + dp[1][i]; } for (int j = 2; j <= k; j++) { int cur = j & 1, pre = cur ^ 1; memset(dp[cur], 0, sizeof(dp[cur])); memset(sum[cur], 0, sizeof(sum[cur])); for (int i = 1; i <= n; i++) { if (s[i] == t[j]) { int where = i - h[t[j - 1] - 'A'] - 1; if (where > 0) M(dp[cur][i] += sum[pre][where]); } //if (i == 2) printf("%d\n", dp[cur][i]); M(sum[cur][i] += sum[cur][i - 1]); M(sum[cur][i] += dp[cur][i]); } } printf("%d\n", sum[k & 1][n]); return 0; }