1. 程式人生 > >bzoj3756pty的字符串(後綴自動機+計數)

bzoj3756pty的字符串(後綴自動機+計數)

貢獻 trie樹 image define clu col color amp +=

題目描述

技術分享圖片

題解

我們可以先對trie樹建出廣義SAM,然後維護一下right集合大小(註意right集合在廣義SAM上的維護方式)。

然後把匹配穿往廣義SAM上匹配,假設現在匹配到了x節點,那麽x的所有祖先後可以被匹配上,那麽一個節點的貢獻即為r[x]*(l[x]-l[fa[x]])

維護這玩意的和就好了,最下面的節點特判一下。

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1600002
#define M 8000002 
using namespace std;
typedef 
long long ll; char c[1],s[M]; int cnt,n,father,pa[N],len,tong[N],rnk[N]; ll sum[N],ans; int l[N],ch[N][26],fa[N],r[N]; inline int rd(){ int x=0;char c=getchar();bool f=0; while(!isdigit(c)){if(c==-)f=1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x; } inline int ins(int last,int x){ int p=last; if(ch[p][x]){ int q=ch[p][x]; if(l[p]+1==l[q]){r[q]++;return q;} else{ int nq=++cnt;l[nq]=l[p]+1;r[nq]=1;//care!!!!!!!!!!!!!!! memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q];fa[q]=nq;
for(;ch[p][x]==q;p=fa[p])ch[p][x]=nq; return nq; } } else{ int np=++cnt;l[np]=l[p]+1;r[np]=1; for(;p&&!ch[p][x];p=fa[p])ch[p][x]=np; if(!p)fa[np]=1; else{ int q=ch[p][x]; if(l[p]+1==l[q])fa[np]=q; else{ int nq=++cnt;l[nq]=l[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q];fa[q]=fa[np]=nq; for(;ch[p][x]==q;p=fa[p])ch[p][x]=nq; } } return np; } } int main(){ n=rd();cnt=1;pa[1]=1; for(int i=2;i<=n;++i){ father=rd();scanf("%s",c); pa[i]=ins(pa[father],c[0]-a); } scanf("%s",s+1);len=strlen(s+1); for(int i=1;i<=cnt;++i)tong[l[i]]++; for(int i=1;i<=n;++i)tong[i]+=tong[i-1]; for(int i=1;i<=cnt;++i)rnk[tong[l[i]]--]=i; for(int i=cnt;i>=1;--i){int x=rnk[i];r[fa[x]]+=r[x];} r[1]=0; for(int i=1;i<=cnt;++i){int x=rnk[i];sum[x]=sum[fa[x]]+1ll*(l[x]-l[fa[x]])*r[x];} int now=1,le=0; for(int i=1;i<=len;++i){ if(ch[now][s[i]-a])le++,now=ch[now][s[i]-a]; else{ for(;now&&!ch[now][s[i]-a];now=fa[now]); if(now)le=l[now]+1,now=ch[now][s[i]-a]; else le=0,now=1; } if(now!=1)ans+=sum[fa[now]]+1ll*(le-l[fa[now]])*r[now]; } cout<<ans; return 0; }
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1600002
#define M 8000002 
using namespace std;
typedef long long ll;
char c[1],s[M];
int cnt,n,father,pa[N],len,tong[N],rnk[N];
ll sum[N],ans;
int l[N],ch[N][26],fa[N],r[N]; 
inline int rd(){
    int x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c==-)f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
inline int ins(int last,int x){
    int p=last;
    if(ch[p][x]){
        int q=ch[p][x];
        if(l[p]+1==l[q]){r[q]++;return q;}
        else{
            int nq=++cnt;l[nq]=l[p]+1;r[nq]=1;//care!!!!!!!!!!!!!!!
            memcpy(ch[nq],ch[q],sizeof(ch[q]));
            fa[nq]=fa[q];fa[q]=nq;
            for(;ch[p][x]==q;p=fa[p])ch[p][x]=nq;
            return nq;
        }
    } 
    else{
        int np=++cnt;l[np]=l[p]+1;r[np]=1;
        for(;p&&!ch[p][x];p=fa[p])ch[p][x]=np;
        if(!p)fa[np]=1;
        else{
            int q=ch[p][x];
            if(l[p]+1==l[q])fa[np]=q;
            else{
                int nq=++cnt;l[nq]=l[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];fa[q]=fa[np]=nq;
                for(;ch[p][x]==q;p=fa[p])ch[p][x]=nq;
            }
        }
        return np;
    }
}
int main(){
    n=rd();cnt=1;pa[1]=1;
    for(int i=2;i<=n;++i){
        father=rd();scanf("%s",c);
        pa[i]=ins(pa[father],c[0]-a);
    }
    scanf("%s",s+1);len=strlen(s+1); 
    for(int i=1;i<=cnt;++i)tong[l[i]]++;
    for(int i=1;i<=n;++i)tong[i]+=tong[i-1];
    for(int i=1;i<=cnt;++i)rnk[tong[l[i]]--]=i;
    for(int i=cnt;i>=1;--i){int x=rnk[i];r[fa[x]]+=r[x];}
    r[1]=0;
    for(int i=1;i<=cnt;++i){int x=rnk[i];sum[x]=sum[fa[x]]+1ll*(l[x]-l[fa[x]])*r[x];}
    int now=1,le=0;
    for(int i=1;i<=len;++i){
        if(ch[now][s[i]-a])le++,now=ch[now][s[i]-a];
        else{
            for(;now&&!ch[now][s[i]-a];now=fa[now]);
            if(now)le=l[now]+1,now=ch[now][s[i]-a];
            else le=0,now=1;
        }
        if(now!=1)ans+=sum[fa[now]]+1ll*(le-l[fa[now]])*r[now];
    }
    cout<<ans;
    return 0;
}

bzoj3756pty的字符串(後綴自動機+計數)