您的位置:首页 > 其它

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

2015-01-02 11:19 218 查看




Online Judge
Online Exercise
Online Teaching
Online Contests
Exercise Author

F.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 2
abc
2
1 a
2
1 a
2




Sample Output

0
1
1


题意:两种操作,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: