题面
解法
感觉自己以前从来没学过KMP……不知道学得什么东西
- 既然题目里面已经明确要求使用KMP了,那就KMP了
- 设 表示字符串以 结尾的前缀中前缀等于后缀的字符串个数(包括自己)
- 可以发现, 可以在求解 的时候计算出来,即
- 这样,我们就得到了一个弱化版的 数组
- 考虑
数组怎么求,其实我们没有必要每一次都花
的时间求出不大于这个前缀长度一半的位置,可以直接借用上一次的位置继续做,和KMP算法在匹配字符串的过程中类似
- 时间复杂度:
代码
#include <bits/stdc++.h>
#define Mod 1000000007
#define N 1000010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
x = 0; int f = 1; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
char st[N];
int nxt[N], cnt[N];
int main() {
int T; read(T);
while (T--) {
scanf(" %s", st + 1);
int l = strlen(st + 1);
nxt[1] = 0, cnt[1] = 1;
for (int i = 2; i <= l; i++) {
int j = nxt[i - 1];
while (j && st[i] != st[j + 1]) j = nxt[j];
if (st[i] == st[j + 1]) j++;
nxt[i] = j, cnt[i] = cnt[nxt[i]] + 1;
}
int ans = 1, j = 0;
for (int i = 2; i <= l; i++) {
while (j && st[j + 1] != st[i]) j = nxt[j];
if (st[i] == st[j + 1]) j++;
while (j * 2 > i) j = nxt[j];
ans = 1ll * (cnt[j] + 1) * ans % Mod;
}
cout << ans << "\n";
}
return 0;
}