【UOJ #149】【NOIP 2015】子串
http://uoj.ac/submission/93769
设$f(i,j,k)$表示用了A的前i个字符,分k段构成B的前j个字符的方案数。
$$f(i,j,k)=f(i-1,j,k)+\sum_l f(i-l,j-l,k-1)$$
$$\sum_l f(i-l,j-l,k-1)=sum(i,j,k)$$
$$sum(i,j,k)=[A(i)=B(j)](sum(i-1,j-1,k)+f(i-1,j-1,k-1))$$
时间复杂度$O(nmk)$
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int p = 1000000007;
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = (k << 3) + (k << 1) + c - '0';
return k * fh;
}
int f[203][203], sum[203][203], la, lb, step;
char A[1003], B[203];
int main() {
la = in(); lb = in(); step = in();
scanf("%s%s", A + 1, B + 1);
f[0][0] = 1;
for(int i = 1; i <= la; ++i)
for(int j = lb; j >= 1; --j)
if (A[i] == B[j])
for(int k = min(step, j); k >= 1; --k) {
sum[j][k] = (sum[j - 1][k] + f[j - 1][k - 1]) % p;
f[j][k] = (f[j][k] + sum[j][k]) % p;
}
else
memset(sum[j], 0, sizeof(int) * (min(step, j) + 1));
printf("%d\n", f[lb][step]);
return 0;
}
~
NOI 2017 Bless All

浙公网安备 33010602011771号