Codeforces 1163D(kmp、dp)

要点

  • (dp[i][j][k])表示主串已经到第(i)位时,(s)匹配在(j)位、(t)匹配在(k)位的最大得分
  • 本来就要试填一层循环,如果转移也写在循环里的化复杂度承受不了,于是开两个表kmp预处理一下。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

char ch[1010], s[55], t[55];
int len, ls, lt, Ns[55], Nt[55];
int Ps[55][30], Pt[55][30];
int dp[1010][55][55], ans = 0xcfcfcfcf;

void GetNext(char *s, int len, int *Next, int P[][30]) {
	Next[1] = 0;
	for (int i = 2, j = 0; i <= len; i++) {
		while (j && s[j + 1] != s[i])	j = Next[j];
		if (s[i] == s[j + 1])	j++;
		Next[i] = j;
	}
	for (int i = 0; i <= len; i++)
		for (int c = 0; c < 26; c++) {
			int j = i;
			while (j && s[j + 1] != c + 'a')	j = Next[j];
			if (s[j + 1] == c + 'a')	j++;
			P[i][c] = j;
		}
}

int main() {
	scanf("%s%s%s", ch + 1, s + 1, t + 1);
	len = strlen(ch + 1), ls = strlen(s + 1), lt = strlen(t + 1);
	GetNext(s, ls, Ns, Ps), GetNext(t, lt, Nt, Pt);

	memset(dp, 0xcf, sizeof dp);
	dp[0][0][0] = 0;
	for (int i = 0; i < len; i++)
		for (int j = 0; j <= ls; j++)
			for (int k = 0; k <= lt; k++)
				for (int c = 0; c < 26; c++) {
					if (ch[i + 1] != '*' && ch[i + 1] - 'a' != c)	continue;
					if (dp[i][j][k] == 0xcfcfcfcf)	continue;
					int a = Ps[j][c], b = Pt[k][c];
					dp[i + 1][a][b] = max(dp[i + 1][a][b], dp[i][j][k] + (a == ls) - (b == lt));
				}
	for (int i = 0; i <= ls; i++)
		for (int j = 0; j <= lt; j++)
			ans = max(ans, dp[len][i][j]);
	return !printf("%d
", ans);
}
原文地址:https://www.cnblogs.com/AlphaWA/p/10884098.html