题目大意 :给你一个串问前缀和后缀相同的情况下子串出现了多少次 ,输出相同的串数,并且输出出现个数
题目分析: 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; } }