文章目录
- 题目描述
- 解析
- 问题
- 总结
- 代码
题目描述
解析
我们可以看到
如果A是B的周期
那么B一定可以写成:
A1A2A1
的形式
注意到:A1就是KMP中的公共前后缀
要使A最大,要使A1最短
也就是求最短公共前后缀
这怎么求呢?
我们注意到:
B的最短前后缀,其实也是B的最长前后缀(就是KMP处理出来的那个东西)的最短前后缀
所以递归求解即可,过程类似于并查集
边界条件:失配数组为0时返回本身
int find(int x){return p[x] ? p[x]=find(p[x]) : x;
}
问题
这题看了题解
一开始思路其实差不多
但就是觉得似乎考虑不到最短公共前后缀大于字符串长度一半的情形
但后来自己又想想其实这样使不存在的
如图
它一定还会存在更短的公共前后缀(就是图中红色的部分)
这样就解决啦
总结
对KMP的理解还是要加深一些
本题类似并查集的方法找最短公共前后缀的方法也值得借鉴
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+100;
char s[N];
int p[N],l,k;
void solve(){p[1]=0;for(int i=1,j=0;i<=l;i++){while(j>0&&s[i+1]!=s[j+1]) j=p[j];if(s[i+1]==s[j+1]) j++;p[i+1]=j;}return;
}
int find(int x){return p[x] ? p[x]=find(p[x]) : x;
}
int main(){scanf("%d",&k);scanf(" %s",s+1);l=strlen(s+1);solve();ll ans=0;for(int i=1;i<=l;i++) ans+=i-find(i);printf("%lld",ans);
}