哈哈哈今天晚上ig VS tes, ig 居然赢了,作为極粉的我真的很开心, 写一下今天下午做的题目吧,是一个kmp + 状态机的题目, 之前做过一个这样的题目,但是奈何做题数量真的不多,一开始还是不清楚做题方向,还在向贪心的方向上想了一会(指半小时),后来知道是dp之后自己也是独立的做出来了, 想想自己还是有一点实力, 就是要自信点,大胆的去猜和做,就像小ig一样冲冲冲, 这几天没有ig的比赛了,那就潜心研究下算法!!
首先先想一下这道题目为什么可以利用dp来做呢,其实这道题目也是在进行枚举,对于将可能影响到最佳答案的状态保存下来,对于每个星号都在进行枚举其可能的值,(其实题目中也隐晦的告诉我这道题目要用dp,就是题目中提到了所有的字母都是小写字母,这样我们明确了可以枚举的种类, 但是为什么我在写题解的时候才发现这一点。。),然后剩下的就是正常的kmp 加状态机了。
这里还需要注意一下当 j == len 时,我们需要将值更新到ne[j] 上,当然其实0 - ne[j] 都应该更新上,只是不影响最优解罢了。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1100, M = 60;
char a[N], b[N], c[N];
int ne_c[N], ne_b[N], f[N][M][M];
int main()
{
scanf("%s%s%s", a + 1, b + 1, c + 1);
int len_a = strlen(a + 1), len_b = strlen(b + 1), len_c = strlen(c + 1);
for (int i = 2, j = 0; i <= len_c; i++)
{
while (j && c[j + 1] != c[i]) j = ne_c[j];
if (c[j + 1] == c[i]) j++;
ne_c[i] = j;
}
for (int j = 0, i = 2; i <= len_b; i++)
{
while (j && b[j + 1] != b[i]) j = ne_b[j];
if (b[j + 1] == b[i]) j++;
ne_b[i] = j;
}
memset(f, -0x3f, sizeof f);
f[1][0][0] = 0;
for (int i = 1; i <= len_a; i++)
{
for (char jz = 'a'; jz <= 'z'; jz++)
for (int k = 0; k <= len_b - 1; k++)
for (int r = 0; r <= len_c - 1; r++)
{
int t1 = k, t2 = r, t = 0;
char j = a[i];
if (a[i] == '*') j = jz;
while (t1 && b[t1 + 1] != j) t1 = ne_b[t1];
if (b[t1 + 1] == j) t1++;
while (t2 && c[t2 + 1] != j) t2 = ne_c[t2];
if (c[t2 + 1] == j) t2++;
if (t2 == len_c) t2 = ne_c[t2], t--;
if (t1 == len_b) t1 = ne_b[t1], t++;
f[i + 1][t1][t2] = max(f[i + 1][t1][t2], f[i][k][r] + t);
}
}
int res = -1e9;
for (int i = 0; i <= len_b; i++)
for (int j = 0; j <= len_c; j++) res = max(res, f[len_a + 1][i][j]);
printf("%d", res);
return 0;
}