原题链接
题意:给你一个字符串s,让你求出一个前缀和后缀相等,并在字符串s中出现的次数。
解法:kmp,对于kmp中的next数组next[j]表示在模板串s[1,j]中前缀和后缀相同的最大长度。那么我们就可以通过kmp的next数组进行匹配。
next[len]获得的就是 前缀1-next[len]匹配的后缀len-next[len]+1。
next[next[len]]表示前缀子串1-next[next[len]]匹配的n-next[next[len]]+1-len后缀,之后通过这个性质,我们可以利用这个来通过dp进行计数,dp(i)表示字符串在字符串s中出现的次数
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define sc scanf
#define pr printf
#define INF 0x3f3f3f3f
const int maxn = 1e5 + 10;
int dp[maxn],Len[maxn],Next[maxn];
char str[maxn];
int top;
void get_next(int len){
for(int i = 2,j = 0; i <= len; i++){
while(j && str[i] != str[j + 1])j = Next[j];
if(str[i] == str[j + 1])j++;
Next[i] = j;
}
}
void solve(){
scanf("%s",str+1);
int len = strlen(str + 1);
get_next(len);
for(int i = len; i >= 1; i = Next[i]){
Len[++top] = i;
}
for(int i = len;i >= 1; i--){
dp[Next[i]] += ++dp[i];
}
printf("%d\n",top);
for(int i = top; i >= 1; i--){
printf("%d %d\n",Len[i],dp[Len[i]]);
}
}
int main(){
int t;
t = 1;
while(t--)
solve();
}