【洛谷P3435】OKR-Periods of Words【KMP】
题目大意:
题目链接:https://www.luogu.org/problemnew/show/P3435
求一个字符串“前缀的前缀”的长度和。
思路:
“前缀的前缀”。。。难道不像数组吗?
首先先求出一个正常的数组,之后很容易发现,也是的一个前缀,那么就很容易了。对于每一个,求出大于0的最小的,然后长度为的答案就是。
之后考虑优化。很容易发现,数组的递归次数太多了,需要减少。那么就每次求出时,优化(因为其他都没用了,反正最后都要跳到),那么当以后的时,就可以直接跳到了。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int len,j,next[1000101];
long long sum;
char s[1000101];
int main()
{
scanf("%d",&len);
cin>>s;
j=0;
for (int i=1;i<len;i++) //求next数组
{
while (j&&s[i]!=s[j]) j=next[j];
if (s[i]==s[j]) j++;
next[i+1]=j;
}
for (int i=1;i<=len;i++)
{
j=i;
while (j&&next[j]) j=next[j];
if (next[i]) next[i]=j; //优化,减少次数
sum+=(long long)(i-j);
}
cout<<sum;
return 0;
}