嗯 看别人的方法千篇一律(都是 kmp)
想个另类方法解决
其实本质上差不多 Orz
HDU 3336
是个前缀问题
并且有个规律 --------- 下一位可能的情况 只有在这一位可能的基础上才有可能
比如
abcabcaca
先把 四个a入链表
对于 ab 只可能 是 上一位是 a 的情况下才有可能
所以 把第三和第四个a 出链表
此时 链表中 还剩 2个元素
当c入队时在继续筛选
这样子快速的原因很明显
越往后找寻的元素越少
…
所以很明显可以用一个循环链表来写 (快速删除一些不合格元素)
#include <iostream>
#include <string.h>
using namespace std;
const int maxn = 2e5 + 5;
const int mod = 1e4 + 7;
char s[maxn];
bool ke[maxn];
struct Node{
int to;
int num;
int p; // 前驱节点
int next; // 后继节点
}whn[maxn];
int cnt, head;
int main() {
int t;
cin >> t;
while (t--) {
cnt = 0;
int n;
cin >> n;
scanf("%s", s);
int ans = 0;
int zong = 0;
for (int i = 0; i < n; i++) {
if (s[i] == s[0]) {
whn[head].p = ++cnt;
whn[cnt].to = i;
whn[cnt].next = cnt + 1;;
whn[cnt].p = cnt - 1;
zong++;
}
}
whn[head].next = 1;
whn[cnt].next = head;
for (int i = 0; i < n && zong; i++) {
for (int j = whn[head].next; j != head; j = whn[j].next) {
if (whn[j].to + i >= n || s[whn[j].to + i] != s[i]) {
zong--;
whn[whn[j].p].next = whn[j].next;
whn[whn[j].next].p = whn[j].p;
}
}
ans = (ans + zong) % mod;
}
cout << ans << endl;
}
return 0;
}