【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;
}

~

posted @ 2016-08-24 15:35  abclzr  阅读(147)  评论(0编辑  收藏  举报