2018.12.24-3881-[Coci2015]Divljak

算法標籤:AC自動機

思路:

咱們能夠先把全部s串在AC 自動機上跑一遍,考慮若是一個串出現了,則我所能指向的全部fail節點均可以得到貢獻,因而咱們建出一棵fail樹。c++

接下來考慮把T串加入,本身思考咱們發現若是隻是單純把我到根節點的路徑權值都+1,咱們可能會重複計算答案,因而就要樹鏈合併,即按照dfs序排序後,每一隻修改我和上一個點的lca到個人路徑,就不會重複。有點卡空間,個人作法是lca用線段樹維護區間d最小值找出lca,時間(常數大)換空間了。git

沒有強制在線因此能夠用AC自動機寫,若是強制在線bzoj2555,就只能用數據結構套數據結構維護了,可怕。算法

如下代碼:

#include<bits/stdc++.h>
#define il inline
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=3e6+5,M=1e5+5;
char s[N];queue<int> q;
int minn[N<<2],ch[N][26],n,Q,tot=1,head[N],ne[N],to[N],num[N<<1],id[N],kk;
int que[N],nt,g[N],d[N],cnt,dfn[N],sz[N],a[N],fail[N],idx;
il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;}
il void insert(int x,int y){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;}
bool cmp(int t1,int t2){return dfn[t1]<dfn[t2];}
il void add(int x,int v){for(;x<=tot;x+=x&-x)g[x]+=v;}
il int query(int x){int ans=0;for(;x;x-=x&-x)ans+=g[x];return ans;}
il int Min(int x,int y){return d[x]<d[y]?x:y;}
il int ins(){
    int l=strlen(s+1);int x=1;
    for(int i=1;i<=l;i++){
        if(!ch[x][s[i]-'a'])ch[x][s[i]-'a']=++tot;
        x=ch[x][s[i]-'a'];
    }
    return x;
}
il void dfs(int x){
    dfn[x]=++idx;sz[x]=1;num[id[x]=++kk]=x;
    for(int i=head[x];i;i=ne[i]){
        d[to[i]]=d[x]+1;dfs(to[i]);
        sz[x]+=sz[to[i]];num[++kk]=x;
    }
}
il void build(int x,int l,int r){
    if(l==r){minn[x]=num[l];return;}
    int mid=(l+r)>>1;
    build(x<<1,l,mid);build(x<<1|1,mid+1,r);
    minn[x]=Min(minn[x<<1],minn[x<<1|1]);
}
il int qm(int x,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr)return minn[x];
    int mid=(l+r)>>1;
    if(qr<=mid)return qm(x<<1,l,mid,ql,qr);
    else if(mid<ql)return qm(x<<1|1,mid+1,r,ql,qr);
    else return Min(qm(x<<1,l,mid,ql,qr),qm(x<<1|1,mid+1,r,ql,qr));
}
il int Lca(int x,int y){
    int l=id[x],r=id[y];if(l>r)swap(l,r);
    return qm(1,1,kk,l,r);
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++){scanf(" %s",s+1);a[i]=ins();}
    q.push(1);
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=0;i<26;i++){
            if(!ch[x][i])continue;
            int tmp=fail[x];
            while(tmp>1&&!ch[tmp][i])tmp=fail[tmp];
            if(ch[tmp][i])fail[ch[x][i]]=ch[tmp][i];
            else fail[ch[x][i]]=1;q.push(ch[x][i]);
        }
    }
    for(int i=2;i<=tot;i++)insert(fail[i],i);
    d[1]=1;dfs(1);build(1,1,kk);int Q=read();
    while(Q--){
        int op=read();
        if(op==1){
            scanf(" %s",s+1);int l=strlen(s+1);
            int x=1,nt=0;que[++nt]=x;
            for(int i=1;i<=l;i++){
                while(x!=1&&!ch[x][s[i]-'a'])x=fail[x];
                if(ch[s[i]-'a'])x=ch[x][s[i]-'a'];que[++nt]=x;
            }
            sort(que+1,que+1+nt,cmp);add(dfn[que[1]],1);
            for(int j=2;j<=nt;j++){
                add(dfn[que[j]],1);
                add(dfn[Lca(que[j],que[j-1])],-1);
            }
        }
        else{
            int x=a[read()];printf("%d\n",query(dfn[x]+sz[x]-1)-query(dfn[x]-1));
        }
    }
    return 0;
}
View Code
本站公眾號
   歡迎關注本站公眾號,獲取更多信息