题目链接
http://noi-test.zzstep.com/contest/0x18%E3%80%8C%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E3%80%8D%E7%BB%83%E4%B9%A0/1809%20%E5%8C%B9%E9%85%8D%E7%BB%9F%E8%AE%A1
分析
求恰好匹配 x x x 长度比较困难,可以转为求至少匹配 x x x 长度的位置,再作差。
用KMP算法可以求出每个位置最多匹配的长度,而这个长度其实是来源于 n e x t [ i ] , n e x t [ n e x t [ i ] ] , . . . next[i], next[next[i]], ... next[i],next[next[i]],...
因此对于他们,求至少匹配 x x x 长度的位置数,应加上他们可以推出的最长匹配长度的位置数。
AC代码
#include <cstdio>
inline int read() {
int num = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9')
num = num * 10 + c - '0', c = getchar();
return num;
}
const int maxn = 2e5 + 5;
int n, m, q, nxt[maxn], f[maxn], cnt[maxn];
char a[maxn], b[maxn];
inline void get_nxt() {
for (int i = 2, j = 0; i <= m; ++i) {
while (j && b[j + 1] != b[i]) j = nxt[j];
if (b[j + 1] == b[i]) ++j;
nxt[i] = j;
}
}
inline void kmp() {
for (int i = 1, j = 0; i <= n; ++i) {
while (j && (j == m ||b[j + 1] != a[i])) j = nxt[j];
if (b[j + 1] == a[i]) ++j;
f[i] = j;
}
}
int main() {
n = read(), m = read(), q = read();
scanf("%s%s", a + 1, b + 1);
get_nxt();
kmp();
for (int i = 1; i <= n; ++i) ++cnt[f[i]];
for (int i = n; i; --i) cnt[nxt[i]] += cnt[i];
for (int i = 1; i <= q; ++i) {
int x = read();
printf("%d\n", cnt[x] - cnt[x + 1]);
}
return 0;
}