【bzoj 4516】生成魔咒(後綴自動機)

傳送門biu~
求本質不同的子串個數,相當於把SAM上的每一個節點表示的長度範圍大小(Max-Min+1)求和。

#include<bits/stdc++.h>
using namespace std;
int n;long long ans;
struct Node{
    map<int,Node*>ch;
    Node* fa;
    int val;
    Node(int _=0){fa=NULL;val=_;}
}*root=new Node,*last=root;
inline void Insert(int x){
    Node *p=last,*np=new Node(p->val+1);
    last=np;
    while(p && !p->ch[x])   p->ch[x]=np,p=p->fa;
    if(!p){
        np->fa=root;
        ans+=np->val;
        return;
    }
    Node *q=p->ch[x];
    if(q->val==p->val+1){
        np->fa=q;
        ans+=np->val-q->val;
        return;
    }
    Node *nq=new Node(p->val+1);
    nq->fa=q->fa;
    nq->ch=q->ch;
    q->fa=np->fa=nq;
    while(p && p->ch[x]==q)  p->ch[x]=nq,p=p->fa;
    ans+=np->val-np->fa->val;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        int x;
        scanf("%d",&x);
        Insert(x);
        printf("%lld\n",ans);
    }
    return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章