题目大意 :给你一个串问前缀和后缀相同的情况下子串出现了多少次 ,输出相同的串数,并且输出出现个数
题目分析: kmp 的next就是匹配与前缀相同多长,所以用最后的next[len]可以知道最长后缀匹配前缀的长度,又最后一个next包含了前一个短的匹配串 所以总共匹配的串数可以用next一直递归下去直到next[i]==0;
而每一个的个数为d[i]+=d[k] ,k>i . d[i]表示 长度为i的子串出现个数 因为每一个长度至少出现一次所以初始化为1, (重点个数统计,理解next函数,当时竟然没发现时kmp ,QAQ)
#include<bits/stdc++.h>
using namespace std;
string s;
stack<pair<int,int> >sta;
int next1[100002];
int vis[1000002];
void getnext(){
next1[0]=-1;
next1[1]=0;
int j=0,i=1,len=s.length();
int add=0;
vis[1]=1;
while(i<len){
if(j==-1||s[j]==s[i])next1[++i]=++j,vis[i]=1;
else j=next1[j];
}
for(int i=len;i>0;i--)
if(next1[i]) vis[next1[i]]+=vis[i];
while(len!=0) sta.push(pair<int,int> (len,vis[len])),len=next1[len];
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
// freopen("1.txt","r",stdin);
memset(vis,0,sizeof(vis));
cin>>s;
getnext();
cout<<sta.size()<<endl;
while(!sta.empty()){
pair<int,int> anss=sta.top();
sta.pop();
cout<<anss.first<<' '<<anss.second<<endl;
}
}

京公网安备 11010502036488号