bzoj4231 memories --AC tree automata

bzoj4231 The Memory of Trees

Given a Trie tree, each query string which is on the path from u to v pattern string contains a given number of times T.

Thinking

After considering all the offline mode for establishing string AC automaton, considering the limited range across lca string, kmp to direct violence.

Then we will ask again split into two chains, and may be linked to each query in the chain and then off to dfs, dfs added each time into AC automata match this node, for a period of u to v chain, before we head a certain position in the chain of illegal minus the number of matches, and then at the end of the chain is like adding the total number of matches.

After How ac automatic machine to record a fixed string matching how many times you can build a tree with a BIT fail to dynamically maintain and sub-tree.

/*=======================================
 * Author : ylsoi
 * Time : 2019.7.2
 * Problem : bzoj4231
 * E-mail : [email protected]
 * ====================================*/
#include<bits/stdc++.h>

#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
#define debug(x) cout<<#x<<"="<<x<<" "
#define DEBUG(x) cerr<<#x<<"="<<x<<" "
#define fi first
#define se second
#define mk make_pair
#define pb push_back
#define pii pair<int,int>
typedef long long ll;

using namespace std;

void File(){
    freopen("bzoj4231.in","r",stdin);
    freopen("bzoj4231.out","w",stdout);
}

template<typename T>void read(T &_){
    _=0; T f=1; char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())_=(_<<1)+(_<<3)+(c^'0');
    _*=f;
}

string proc(){
    ifstream f("/proc/self/status");
    return string(istreambuf_iterator<char>(f),istreambuf_iterator<char>());
}

const int maxn=3e5+10;
int n,m,ans[maxn];
int beg[maxn],to[maxn<<1],las[maxn<<1],cha[maxn<<1],cnte=1;

void add(int u,int v,int c){
    las[++cnte]=beg[u],beg[u]=cnte,to[cnte]=v,cha[cnte]=c;
    las[++cnte]=beg[v],beg[v]=cnte,to[cnte]=u,cha[cnte]=c;
}

namespace aca{
    int ch[maxn][26],fail[maxn],cnt;
    int dfn[maxn],sz[maxn],cnt_dfn;
    int sum[maxn];
    int lowbit(int x){return x&(-x);}
    vector<int>G[maxn];
    int insert(int len,char *t){
        int o=0,c;
        REP(i,1,len){
            c=t[i]-'a';
            if(!ch[o][c])ch[o][c]=++cnt;
            o=ch[o][c];
        }
        return o;
    }
    void get_fail(){
        queue<int>qu;
        REP(i,0,25)if(ch[0][i])qu.push(ch[0][i]);
        while(!qu.empty()){
            int u=qu.front(); qu.pop();
            REP(i,0,25){
                int v=ch[u][i];
                if(v)fail[v]=ch[fail[u]][i],qu.push(v);
                else ch[u][i]=ch[fail[u]][i];
            }
        }
        REP(i,1,cnt)G[fail[i]].push_back(i);
    }
    void dfs(int u){
        dfn[u]=++cnt_dfn,sz[u]=1;
        REP(i,0,G[u].size()-1){
            int v=G[u][i];
            dfs(v),sz[u]+=sz[v];
        }
    }
    void update(int u,int x){
        u=dfn[u];
        for(;u<=cnt_dfn;u+=lowbit(u))sum[u]+=x;
    }
    int query(int u){
        int l=dfn[u]-1,r=dfn[u]+sz[u]-1,ret=0;
        for(;l>=1;l-=lowbit(l))ret-=sum[l];
        for(;r>=1;r-=lowbit(r))ret+=sum[r];
        return ret;
    }
}

int st[maxn][21],Log[maxn],dep[maxn],fa_ch[maxn];

void dfs(int u,int fh){
    st[u][0]=fh,dep[u]=dep[fh]+1;
    for(int i=beg[u];i;i=las[i]){
        int v=to[i];
        if(v==fh)continue;
        fa_ch[v]=cha[i];
        dfs(v,u);
    }
}

int lca(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int d=Log[dep[x]-dep[y]];dep[x]!=dep[y];--d)
        if(dep[st[x][d]]>=dep[y])x=st[x][d];
    if(x==y)return x;
    for(int d=Log[dep[x]];d>=0;--d)
        if(st[x][d]!=st[y][d])
            x=st[x][d],y=st[y][d];
    return st[x][0];
}

int kth(int x,int k){
    if(k<0)return x;
    REP(i,0,Log[k])if(1<<i&k)x=st[x][i];
    return x;
}

int kmp(char *s,char *t,int lens,int lent){
    if(lens<lent)return 0;
    reverse(s,s+lens);
    static int fail[maxn];
    fail[0]=fail[1]=0;
    REP(i,1,lent-1){
        int j=fail[i];
        while(j && t[j]!=t[i])j=fail[j];
        if(t[j]==t[i])fail[i+1]=j+1;
        else fail[i+1]=0;
    }
    int j=0,ret=0;
    REP(i,0,lens-1){
        while(j && s[i]!=t[j])j=fail[j];
        if(s[i]==t[j])++j;
        if(j==lent)++ret;
    }
    return ret;
}

struct node{int id,o,ty;};
vector<node>qu[maxn];

void solve(int u,int o,int fh){
    using namespace aca;
    if(u!=1){
        int c=fa_ch[u];
        o=ch[o][c];
        update(o,1);
    }
    REP(i,0,qu[u].size()-1){
        ans[qu[u][i].id]+=qu[u][i].ty*query(qu[u][i].o);
    }
    for(int i=beg[u];i;i=las[i]){
        int v=to[i];
        if(v==fh)continue;
        solve(v,o,u);
    }
    if(u!=1)update(o,-1);
}

int main(){
    File();

    read(n),read(m);

    int u,v,anc;
    static char s[maxn],t[maxn];
    REP(i,2,n){
        read(u),read(v),scanf("%s",t);
        add(u,v,t[0]-'a');
    }
    dfs(1,0);
    REP(i,2,n)Log[i]=Log[i>>1]+1;
    REP(j,1,Log[n])REP(i,1,n)
        if(dep[i]-(1<<j)>=1)
            st[i][j]=st[st[i][j-1]][j-1];


    REP(i,1,m){
        read(u),read(v);
        scanf("%s",t+1);
        int len=strlen(t+1);
        anc=lca(u,v);
        int p1=aca::insert(len,t);
        reverse(t+1,t+len+1);
        int p2=aca::insert(len,t);
        int cnt=0;
        int u1=kth(u,dep[u]-dep[anc]-len+1),u2=u1;
        REP(j,1,dep[u1]-dep[anc])s[++cnt]='a'+fa_ch[u2],u2=st[u2][0];
        if(dep[u]-dep[anc]>=len){
            qu[u1].push_back((node){i,p2,-1});
            qu[u].push_back((node){i,p2,1});
        }
        int v1=kth(v,dep[v]-dep[anc]-len+1),v2=v1;
        cnt+=dep[v1]-dep[anc];
        REP(j,1,dep[v1]-dep[anc])s[cnt-j+1]='a'+fa_ch[v2],v2=st[v2][0];
        if(dep[v]-dep[anc]>=len){
            qu[v1].push_back((node){i,p1,-1});
            qu[v].push_back((node){i,p1,1});
        }
        s[cnt+1]='\0';
        ans[i]+=kmp(s+1,t+1,cnt,len);
    }

    aca::get_fail();
    aca::dfs(0);

    solve(1,0,0);

    REP(i,1,m)printf("%d\n",ans[i]);

    return 0;
}

Guess you like

Origin www.cnblogs.com/ylsoi/p/11122931.html