Awesome Brother Gym - 102020A (kmp优化dp)

kmp优化dp
https://vjudge.net/problem/Gym-102020A

vector<int> v[10];
char M[111];
int n, m, k;
ll dp[10010][101][10];
int kmp[10010];
int pre[10010][12];
int nxt[10010];

void get_next(char* s, int* next) {
	int len = strlen(s);
	int k = next[0] = -1;
	for (int i = 0; i < len; ) {
		if (k == -1 || s[i] == s[k]) {
			next[++i] = ++k;
		}
		else
			k = next[k];
	}
}

int failureFunction(char* p) {
	int len = strlen(p), cnt = 0;
	strcat(p, "#");
	int now = kmp[0] = -1;
	for (int i = 0; i < 10; ++i)	pre[0][i] = -1;
	for (int i = 1; p[i]; ++i) {
		for (int j = 0; j < 10; ++j) {
			int tmp = now;
			char ch = j + '0';
			while (tmp != -1 && p[tmp + 1] != ch)	tmp = kmp[tmp];
			if (ch == p[tmp + 1])	pre[i][j] = ++tmp;
			else pre[i][j] = tmp = -1;
		}

		while (now != -1 && p[now + 1] != p[i])	now = kmp[now];
		if (p[now + 1] == p[i])	kmp[i] = ++now;
		else kmp[i] = now = -1;
		if (now == len - 1)	cnt++;
	}
	return cnt;
}



ll solve(int pos, int match, int now) {
	if (m and match == m)	return 0;
	if (pos == n)	return 1ll;
	ll& res = dp[pos][match][now];
	if (~res)	return res;
	res = 0;
	for (auto& x : v[now]) {
		char nxt = x + '0';
		if (nxt == M[match])	res += solve(pos + 1, match + 1, x);
		else if (match == 0)		res += solve(pos + 1, 0, x);
		else res += solve(pos + 1, pre[match][x] + 1, x);
		res %= mod;
	}
	return res;
}

signed main() {
	v[0] = { 4, 6 }; 
	v[1] = { 6, 8 };
	v[2] = { 7, 9 };
	v[3] = { 4, 8 };
	v[4] = { 0, 3, 9 };
	v[5] = {};
	v[6] = { 0, 1, 7 };
	v[7] = { 2, 6 };
	v[8] = { 1, 3 };
	v[9] = { 2, 4 };
	memset(dp, -1, sizeof dp);
	scanf("%lld %lld %lld", &n, &m, &k);
	if (m)	scanf("%s", M);
	else M[0] = '\0';
	failureFunction(M);
	printf("%lld\n", solve(0, 0, k));
	return 0;
}

posted @ 2021-03-06 22:17  wansheking  阅读(82)  评论(0)    收藏  举报