Live2d Test Env

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).
 

 

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;
}

 

posted @ 2017-11-25 12:14  nimphy  阅读(346)  评论(0编辑  收藏  举报