Link
解题思路
给出一个A
黄线为最短的前缀 = 后缀
很明显周期Q应该选前三个
QQ即为
粉色部分就是A啦
最长的Q = A - 最短后缀
这样就保证QQ中一定有A
即合法且最长
最短后缀长度只需不停地往前跳next[]就可以了
Code
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
long long n, ans, k, next[10010000];
char s[1001000];
int find(int x) {
if (next[x]) {
//不停地往前跳next[],直到找到没有next[]的地方,也就是最短的前缀——后缀
next[x] = find(next[x]); //类似并查集缩短路径
return next[x];
}
return x;
}
int main() {
scanf("%lld", &n);
for (int i = 1; i <= n; i++)
cin >> s[i];
for (int i = 1; i <= n; i++) { //跑一遍kmp
while(k != 0 && s[i + 1] != s[k + 1])
k = next[k];
if (s[i + 1] == s[k + 1])
k++;
next[i + 1] = k;
}
for (int i = 1; i <= n; i++)
ans += i - find(i); //A - 最短后缀
printf("%lld", ans);
}