题意
传送门 Codeforces 808G Anthem of Berland
题解
设 d p [ i + 1 ] [ j ] dp[i+1][j] dp[i+1][j] 代表以 i i i 为结尾的 s s s 前缀与 t t t 的最长匹配长度为 j j j 时,模式串 t t t 在 s s s 前缀中出现的最多次数。 K M P KMP KMP 建自动机求解即可。总时间复杂度 O ( 26 × ∣ s ∣ × ∣ t ∣ ) O(26\times\lvert s\rvert\times\lvert t\rvert) O(26×∣s∣×∣t∣)
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l, _ = r; i < _; ++i)
const int MAXN = 1E+5;
string S, T;
int b[MAXN], aut[MAXN][26];
int dp[2][MAXN];
void kmp(string &s)
{
int n = s.size();
int i = 0, j = -1;
b[i] = j;
while (i < n)
{
while (j >= 0 && s[i] != s[j])
j = b[j];
++i, ++j;
b[i] = j;
}
rep(i, 0, n) rep(j, 0, 26) aut[i][j] = s[i] - 'a' == j ? i + 1 : (b[i] == -1 ? 0 : aut[b[i]][j]);
}
void _max(int &x, int y) { x = max(x, y); }
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> S >> T;
kmp(T);
int n = S.size(), m = T.size();
auto cur = dp[0], nxt = dp[1];
memset(cur, 0xc0, sizeof(int) * m);
cur[0] = 0;
rep(i, 0, n)
{
memset(nxt, 0xc0, sizeof(int) * m);
rep(j, 0, m)
{
if (cur[j] < 0)
continue;
if (S[i] != '?')
{
int t = aut[j][S[i] - 'a'];
if (t == m)
_max(nxt[b[m]], cur[j] + 1);
else
_max(nxt[t], cur[j]);
}
else
{
rep(k, 0, 26)
{
int t = aut[j][k];
if (t == m)
_max(nxt[b[m]], cur[j] + 1);
else
_max(nxt[t], cur[j]);
}
}
}
swap(cur, nxt);
}
int res = 0;
rep(i, 0, m) res = max(res, cur[i]);
cout << res << '\n';
return 0;
}