题意:给你一个字符串s,请你找到所有的特殊字符串,满足它既是s的前缀,又是s的后缀,并输出它在s中出现的次数。
做法:对于第一步,我们只需要先做出kmp,考虑kmp中ne数组的意义,不就是求border吗,那么我们一直去求最后一个字符串字母的border,然后就能把所有的既是前缀又是后缀的字符串求出来了。然后下一步我们要求这玩意出现在字符串中的次数,考虑拓展kmp中z函数的意义,在求z函数的时候开一个数组cnt来记录该前缀对应出现的次数,然后就a了哈哈哈
#include <bits/stdc++.h> using namespace std; int ans[100010]; int ans1[100010]; void solve() { string a; cin>>a; int n=a.size(); vector<int>ne(n+1); for(int i=1,j=0;i<n;i++) { while(j&&a[j]!=a[i])j=ne[j-1]; if(a[j]==a[i])j++; ne[i]=j; } int p=ne[n-1]; while(p!=0) { ans[p]++; p=ne[p-1]; } ans[n]++; vector<int>z(n+1); for(int i=1,l=0,r=0;i<n;i++) { if(z[i-l]<r-i+1) z[i]=z[i-l]; else { z[i]=max(0,r-i+1); while(i+z[i]<n&&a[i+z[i]]==a[z[i]])z[i]++; l=i; r=i+z[i]-1; } } for(int i=0;i<n;i++) { ans1[z[i]]++; } ans1[n]++; for(int i=n-1;i>=1;i--) { ans1[i]+=ans1[i+1]; } int cnt=0; for(int i=1;i<=n;i++) { if(ans[i])cnt++; } cout<<cnt<<"\n"; for(int i=1;i<=n;i++) { if(ans[i]) cout<<i<<" "<<ans1[i]<<"\n"; } } signed main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); // int t = 1; // cin >> t; // while (t--) solve(); return 0; }