HDU4641 K-string(后缀自动机)
Problem Description
Given a string S. K-string is the sub-string of S and it appear in the S at least K times.It means there are at least K different pairs (i,j) so that Si,Si+1... Sj equal to this K-string. Given m operator or query:1.add a letter to the end of S; 2.query how many different K-string currently.For each query ,count the number of different K-string currently.
Input
The input consists of multiple test cases.
Each test case begins with a line containing three integers n, m and K(1<=n,K<=50000,1<=m<=200000), denoting the length of string S, the number of operator or question and the least number of occurrences of K-string in the S.
The second line consists string S,which only contains lowercase letters.
The next m lines describe the operator or query.The description of the operator looks as two space-separated integers t c (t = 1; c is lowercase letter).The description of the query looks as one integer t (t = 2).
Each test case begins with a line containing three integers n, m and K(1<=n,K<=50000,1<=m<=200000), denoting the length of string S, the number of operator or question and the least number of occurrences of K-string in the S.
The second line consists string S,which only contains lowercase letters.
The next m lines describe the operator or query.The description of the operator looks as two space-separated integers t c (t = 1; c is lowercase letter).The description of the query looks as one integer t (t = 2).
Output
For each query print an integer — the number of different K-string currently.
Sample Input
3 5 2
abc
2
1 a
2
1 a
2
Sample Output
0
1
1
关键词:在线处理;不需要topsort;避免重复。
合理剪枝,只处理maxlen-minlen+1==k的情况,>k不作考虑,如果和上一道题一样记录used就会超时。
#include<iostream> #include<cstring> #include<cstdio> #include<cstring> #include<algorithm> #include<string> using namespace std; const int maxn=300100; int tot,slink[2*maxn],trans[2*maxn][26],maxlen[2*maxn]; char str[maxn]; int N,M,K,num[2*maxn],last; long long ans; void init() { ans=tot=0; last=0; memset(trans[0],-1,sizeof(trans[0])); slink[0]=-1; maxlen[0]=0; } void add_char(char chr) { int c=chr-'a'; int p=last,np=++tot; maxlen[np]=maxlen[p]+1; memset(trans[np],-1,sizeof(trans[np])); num[np]=0; while(p!=-1&&trans[p][c]==-1) trans[p][c]=np,p=slink[p]; if(p==-1) slink[np]=0; else { int q=trans[p][c]; if(maxlen[q]!=maxlen[p]+1) { int nq=++tot; memcpy(trans[nq],trans[q],sizeof(trans[q])); num[nq]=num[q]; maxlen[nq]=maxlen[p]+1; slink[nq]=slink[q]; slink[np]=slink[q]=nq; while(p!=-1&&trans[p][c]==q) trans[p][c]=nq,p=slink[p]; } else slink[np]=q; } last=np; while(np!=-1&&num[np]<K) //没有达到K次的就加1 { num[np]++; if(num[np]>=K) ans+=maxlen[np]-maxlen[slink[np]]; //加上答案 np=slink[np]; } } int main() { while(~scanf("%d%d%d",&N,&M,&K)){ char c[2]; init(); scanf("%s",str); for(int i=0; i<N; i++) add_char(str[i]); for(int i=1;i<=M;i++){ int tmp; scanf("%d",&tmp); if(tmp==2) printf("%lld\n",ans); else { scanf("%s",c); add_char(c[0]); } } } return 0; }
It is your time to fight!