后缀自动机(hdu4641多校联合)

来源:互联网 发布:编程不等于怎么表示 编辑:程序博客网 时间:2024/04/27 14:27

Online JudgeOnline ExerciseOnline TeachingOnline ContestsExercise AuthorF.A.Q
Hand In Hand
Online Acmers
Forum | Discuss
Statistical Charts

Problem Archive
Realtime Judge Status
Authors Ranklist
 
     C/C++/Java Exams     
ACM Steps
Go to Job
Contest LiveCast
ICPC@China
Best Coder beta
VIP | STD Contests
Virtual Contests 
    DIY | Web-DIY beta
Recent Contests
Author ID Password  Register new ID
【比赛提醒】BestCoder 你报名了吗?(点击报名) 
【科普】什么是BestCoder?如何参加?

K-string

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 102400/131072 K (Java/Others)
Total Submission(s): 660    Accepted Submission(s): 212


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 2abc21 a21 a2
 

Sample Output
011

题意:两种操作,1是添加字符,2是查询出现K次的不同的子串有多少个

思路:在线添加查询SAM,每次添加的时候顺便维护每个节点出现多少次,询问的时候直接输出就可以了,维护的原理就是根据后缀自动机的性质,父节点跟子节点有相同的后缀,但长度短,所以每次从最后一个节点沿Parent走一遍,经过的点肯定都要加上,然后容斥一下算出每次新加的有多少个

另外用指针真的很慢啊

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<vector>#include<algorithm>using namespace std;typedef long long LL;const int maxn=300010;const int SIGMA_SIZE=26;int N,M,K;LL ans;char s[maxn];struct SAM_Node{    SAM_Node *par,*next[SIGMA_SIZE];    int len,id,pos,cnt;    SAM_Node(){}    SAM_Node(int _len)    {        par=0;        len=_len;        cnt=0;        memset(next,0,sizeof(next));    }};SAM_Node node[maxn*2],*root,*last;int SAM_size;SAM_Node *newSAM_Node(int len){    node[SAM_size]=SAM_Node(len);    node[SAM_size].id=SAM_size;    return &node[SAM_size++];}SAM_Node *newSAM_Node(SAM_Node *p){    node[SAM_size]=*p;    node[SAM_size].id=SAM_size;    return &node[SAM_size++];}void SAM_add(int x){    SAM_Node *p=last,*np=newSAM_Node(p->len+1);    last=np;    while(p&&!p->next[x])    {        p->next[x]=np;        p=p->par;    }    if(!p)        np->par=root;    else    {        SAM_Node *q=p->next[x];        if(q->len==p->len+1)            np->par=q;        else        {            SAM_Node *nq=newSAM_Node(q);            nq->len=p->len+1;            q->par=nq;            np->par=nq;            while(p&&p->next[x]==q)            {                p->next[x]=nq;                p=p->par;            }        }    }    SAM_Node *tmp;    for(tmp=last;tmp;tmp=tmp->par)    {        if(tmp->cnt==K)break;        tmp->cnt++;        if(tmp->cnt==K)        {            int num;            if(!tmp->par)num=0;            else num=tmp->par->len;            ans=ans+(tmp->len)-num;            break;        }    }}void SAM_init(){    SAM_size=0;    root=last=newSAM_Node(0);    node[0].pos=0;}void SAM_build(char *s){    SAM_init();    int len=strlen(s);    for(int i=0;i<len;i++)        SAM_add(s[i]-'a');}int main(){    int op;    char t[5];    while(scanf("%d%d%D",&N,&M,&K)!=EOF)    {        scanf("%s",s);        ans=0;        SAM_build(s);        while(M--)        {            scanf("%d",&op);            if(op==1)            {                scanf("%s",t);                SAM_add(t[0]-'a');            }            else printf("%I64d\n",ans);        }    }    return 0;}





0 0
原创粉丝点击