bzoj4231 memory Tree (AC Automaton +fail tree +KMP (+ tree-like array))

Source: Internet
Author: User
Tags strlen
bzoj4231 Memory Tree

Original title address : http://www.lydsy.com/JudgeOnline/problem.php?id=3881

Test Instructions:
The memory tree is a tree.
Specifically, there is an undirected connected graph of N-point n-1, with a dot labeled 1~n and a character on each edge (for simplification purposes, we consider only lowercase letters).
For a memory tree, of course, memories are indispensable.
One memory is this: you think of the past, touch the bottom of my heart ... Well, no, we have to talk about the topic.
In this case, we think of the memory is this: given 2 points u,v (U may be equal to V) and a non-empty string s, ask the simple path from U to v all the edges in the distance from the U to the beginning of the order from small to large, the characters on the edge stitching the string in the form of the number of times in the case of

Data Range
n<=100000,m<=100000, ask the total length of the string <=300000

The following:
Good question ...
Ask the string in a chain to match how many times, to the memory tree achievements is no way, not like bzoj3926, each leaves proposed to build a tree trie.
So the problem is offline, to query the string (the positive string and crossdress) to build AC automata.

Similarly, a contains string b how many times, is a on the AC automaton each node, how many in the B end node in the Fail tree subtree.
As a result, the Dfs original tree is matched on the AC automaton,

Because the chain is to turn, at the same time there is a direction, this bad treatment, so a chain to split into three parts:
Corner: Length of 2| T|, match with KMP violence
The remaining two paragraph one is a match, one is inverted, so ask the string need to put the positive crossdress are inserted into the AC automata,

So the inquiry becomes a part of the path from the root to a point (straight ...). ), you can work on the DFS side.

Just like the way of running every day, in the corresponding starting point push into the query, as well as whether it is necessary to add or subtract, queries the fail tree which subtree.

Then when the Dfs original tree at the same time on the AC automaton transfer, enter this point to the AC automaton on the corresponding point +1, leaving 1,
Inquiry is to query the value of the fail tree subtree and.

Code:

#include <cstdio> #include <iostream> #include <algorithm> #include <vector> #include <
Cstring> #include <queue> using namespace std;
const int n=110005;
const int m=300015;
Queue<int> Q;
Vector<int> V[n],id[n];
Char Str[m];
    namespace AC {int ch[2*m][26],root,tail,head[2*m],nxt[2*m],to[2*m],num,fail[2*m];
    int in[2*n],out[2*m],inc,c[2*m];
    inline void build (int u,int v) {num++; to[num]=v; nxt[num]=head[u]; head[u]=num; inc=0;}
    inline void init () {root=1,tail=1,num=0;}
        inline int insert (int opt) {int len=strlen (str); int tmp=root;
            for (int j=0,i;j<len;j++) {if (opt==1) i=j; else i=len-j-1;
            int c=str[i]-' a ';
            if (!ch[tmp][c]) Ch[tmp][c]=++tail;
        TMP=CH[TMP][C];
    } return TMP; } inline void Getfail () {for (int i=0;i<26;i++) if (Ch[root][i]) Fail[ch[root][i]]=root,build (Root,ch[ro Ot][i]), Q.push (Ch[root][i]); else Ch[rooT][i]=root; while (! Q.empty ()) {int Top=q.front ();
            Q.pop ();
                for (int i=0;i<26;i++) {if (!ch[top][i]) ch[top][i]=ch[fail[top]][i];
                    else {int u=ch[top][i];
                    Fail[u]=ch[fail[top]][i];
                    Build (Fail[u],u);
                Q.push (U);
        }}}} inline void dfs (int u) {inc++; in[u]=inc;
        for (int i=head[u];i;i=nxt[i]) DFS (to[i]);
    Out[u]=inc;
    } inline void Add (int x,int d) {for (int i=x;i<=inc;i=i+ (i& (i))) C[i]+=d;}

inline int query (int x) {int ret=0;for (int i=x;i;i=i-) (i& (-i)) ret+=c[i]; return ret;}} int head[n],to[2*n],w[2*n],nxt[2*n],num=0,n,m,ans[n],fa[n],dep[n],_w[n],size[n],son[n],top[n],dfn=0,seq[n],loc[
N];
int nx[m],s[m],t[m],pos[n][2];
    inline void build (int u,int v,int ww) {num++;
    W[NUM]=WW;
    To[num]=v; Nxt[num]=head[u];
Head[u]=num;
    } inline void Dfs (int u,int f) {dep[u]=dep[f]+1; fa[u]=f; size[u]=1;
        for (int i=head[u];i;i=nxt[i]) {if (to[i]==f) continue;
        _w[to[i]]=w[i];
        DFS (TO[I],U);
        Size[u]+=size[to[i]];
    if (Size[son[u]]<size[to[i]]) son[u]=to[i];
    }} inline void dfs1 (int u,int f,int tp) {loc[u]=++dfn,seq[dfn]=u; top[u]=tp;
    if (Son[u]) DFS1 (SON[U],U,TP); for (int i=head[u];i;i=nxt[i]) {if (to[i]==f| |
        To[i]==son[u]) continue;
    DFS1 (To[i],u,to[i]);
        }} inline int getlca (int u,int v) {while (Top[u]!=top[v]) {if (Dep[top[u]]<dep[top[v]) swap (U,V);
    U=fa[top[u]];
} return dep[u]<dep[v]?u:v;
    } inline int getpoint (int u,int d) {while (dep[u]-dep[top[u]]<d) {d-= (dep[u]-dep[top[u]]+1), U=fa[top[u]];}
return seq[loc[u]-d];
    } inline void kmp (int u,int v,int lca,int id) {int lent=strlen (str), lens=0; int X=getpoint (U,dep[u]-min (dep[u],dep[lca]+lent-1));   
    int Y=getpoint (V,dep[v]-min (dep[v],dep[lca]+lent-1));
    LENS=DEP[X]-DEP[LCA]+DEP[Y]-DEP[LCA]; int tmp=x,i=0,j;
    while (TMP!=LCA) s[i++]=_w[tmp],tmp=fa[tmp]; Tmp=y,i=1;
    while (TMP!=LCA) s[lens-i]=_w[tmp],tmp=fa[tmp],i++;
    for (int i=0;i<lent;i++) t[i]=str[i]-' a '; Nx[0]=-1;
    I=0,j=-1; while (i<lent) {if (j==-1| |
        T[i]==t[j]) {i++; j + +; nx[i]=j;}
    else J=nx[j]; } i=0,j=0;
    int ret=0; while (I<lens) {if (j==-1| |
            S[i]==t[j]) {i++; j + +;
        if (j==lent) {ret++; j=nx[j];}
    } else j=nx[j]; } pos[id][0]=ac::insert (1);
    Pos[id][1]=ac::insert (-1);
    Ans[id]=ret; if (u!=x) {id[x].push_back (-id);
        Id[u].push_back (ID); V[x].push_back (pos[id][1]);
    V[u].push_back (pos[id][1]); } if (v!=y) {id[y].push_back (-id);
        Id[v].push_back (ID); V[y].push_back (Pos[id][0]);
    V[v].push_back (Pos[id][0]); }} inline void dfs2 (int u,int f,int x)
{Ac::add (ac::in[x],1); 
    int sz=v[u].size ();
        for (int i=0;i<sz;i++) {int ret=ac::query (Ac::out[v[u][i]])-ac::query (ac::in[v[u][i]]-1);
        if (id[u][i]>0) Ans[id[u][i]]+=ret;
    else Ans[-id[u][i]]-=ret;
        } for (int i=head[u];i;i=nxt[i]) {int v=to[i];
        if (v==f) continue;
    DFS2 (V,u,ac::ch[x][w[i]);
} ac::add (ac::in[x],-1);
    } int main () {scanf ("%d%d", &n,&m);
        for (int i=1;i<n;i++) {int u,v; scanf ("%d%d", &u,&v); scanf ("%s", str); Build (u,v,str[0]-' a ');
    Build (v,u,str[0]-' a '); } dfs (a); DFS1 (1,1,1);
    Ac::init ();  for (int i=1;i<=m;i++) {int u,v; scanf ("%d%d", &u,&v);

        scanf ("%s", str); if (u==v) continue; 
        int Lca=getlca (U,V);
    KMP (U,v,lca,i);  
    } ac::getfail ();
    AC::d FS (1);
    DFS2 (1,1,1);
    for (int i=1;i<=m;i++) printf ("%d\n", Ans[i]);
return 0; }

Then this is the double version of the code that I originally wrote (corrected), no namespace set namespace this kind of ghost animal thing:

#include <cstdio> #include <iostream> #include <algorithm> #include <vector> #include <
Cstring> #include <queue> using namespace std;
const int n=100005;
const int m=300015;
const int P=17;
Queue<int> Q;
Vector<int> V[n],id[n];
Char Str[m];
    struct AC_ {int ch[2*m][26],root,tail,head[2*m],nxt[2*m],to[2*m],num,fail[2*m];
    int in[2*n],out[2*m],inc,c[2*m];
    void build (int u,int v) {num++; to[num]=v; nxt[num]=head[u]; head[u]=num; inc=0;}
    void Init () {root=1,tail=1,num=0;}
        int insert (int opt) {int len=strlen (str); int tmp=root;
            for (int j=0,i;j<len;j++) {if (opt==1) i=j; else i=len-j-1;
            int c=str[i]-' a ';
            if (!ch[tmp][c]) Ch[tmp][c]=++tail;
        TMP=CH[TMP][C];
    } return TMP; } void Getfail () {for (int i=0;i<26;i++) if (Ch[root][i]) fail[ch[root][i]]=root,build (Root,ch[root][i]) , Q.push (Ch[root][i]);
  else Ch[root][i]=root;      while (! Q.empty ()) {int Top=q.front ();
            Q.pop ();
                for (int i=0;i<26;i++) {if (!ch[top][i]) ch[top][i]=ch[fail[top]][i];
                    else {int u=ch[top][i];
                    Fail[u]=ch[fail[top]][i];
                    Build (Fail[u],u);
                Q.push (U);
        }}}} void Dfs (int u) {inc++; in[u]=inc;
        for (int i=head[u];i;i=nxt[i]) DFS (to[i]);
    Out[u]=inc;
    } void Add (int x,int d) {for (int i=x;i<=inc;i=i+ (i& (i))) C[i]+=d;} inline int query (int x) {int ret=0;for (int i=x;i;i=i-) (i& (-i)) ret+=c[i]; return ret;}}
AC;
int head[n],to[2*n],w[2*n],nxt[2*n],num=0,n,m,ans[n],anc[n][p+3],dep[n],_w[n];
int nx[m],s[m],t[m],pos[n][2];
    void build (int u,int v,int ww) {num++;
    W[NUM]=WW;
    To[num]=v;
    Nxt[num]=head[u];
Head[u]=num; } void dfs1 (int u,int f) {DEP[U]=DEP[F]+1;
    Anc[u][0]=f;
    for (int i=1;i<p;i++) anc[u][i]=anc[anc[u][i-1]][i-1];
for (int i=head[u];i;i=nxt[i]) if (to[i]!=f) _W[TO[I]]=W[I],DFS1 (to[i],u);
    } inline int Getlca (int u,int v) {if (Dep[u]<dep[v]) swap (U,V);
    int D=DEP[U]-DEP[V];
    for (int i=0;d;d>>=1,i++) if (d&1) u=anc[u][i];
    if (u==v) return u;
    for (int i=p-1;i>=0;i--) if (Anc[u][i]!=anc[v][i]) u=anc[u][i],v=anc[v][i];
return anc[u][0]; } inline int getpoint (int u,int d) {for (int i=0;d;d>>=1,i++) if (d&1) u=anc[u][i]; return u;} void kmp (int u,int
    V,int lca,int ID) {int lent=strlen (str), lens=0;
    int X=getpoint (U,dep[u]-min (dep[u],dep[lca]+lent-1));
    int Y=getpoint (V,dep[v]-min (dep[v],dep[lca]+lent-1));
    LENS=DEP[X]-DEP[LCA]+DEP[Y]-DEP[LCA]; int tmp=x,i=0,j;
    while (TMP!=LCA) s[i++]=_w[tmp],tmp=anc[tmp][0]; Tmp=y,i=1;
    while (TMP!=LCA) s[lens-i]=_w[tmp],tmp=anc[tmp][0],i++;
    for (int i=0;i<lent;i++) t[i]=str[i]-' a '; Nx[0]=-1;
    I=0,j=-1; while (i&Lt;lent) {if (j==-1| |
        T[i]==t[j]) {i++; j + +; nx[i]=j;}
    else J=nx[j]; } i=0,j=0;
    int ret=0; while (I<lens) {if (j==-1| |
            S[i]==t[j]) {i++; j + +;
        if (j==lent) {ret++; j=nx[j];}
    } else j=nx[j]; } pos[id][0]=ac.insert (1);
    Pos[id][1]=ac.insert (-1);
    Ans[id]=ret; if (u!=x) {id[x].push_back (-id);
        Id[u].push_back (ID); V[x].push_back (pos[id][1]);
    V[u].push_back (pos[id][1]); } if (v!=y) {id[y].push_back (-id);
        Id[v].push_back (ID); V[y].push_back (Pos[id][0]);
    V[v].push_back (Pos[id][0]); 
    }} void Dfs2 (int u,int f,int x) {ac.add (ac.in[x],1); 
    int sz=v[u].size ();
        for (int i=0;i<sz;i++) {int ret=ac.query (Ac.out[v[u][i]])-ac.query (ac.in[v[u][i]]-1);
        if (id[u][i]>0) Ans[id[u][i]]+=ret;
    else Ans[-id[u][i]]-=ret;
        } for (int i=head[u];i;i=nxt[i]) {int v=to[i]; if (v==f) ContiNue
    DFS2 (V,u,ac.ch[x][w[i]);
} ac.add (ac.in[x],-1);
    } int main () {scanf ("%d%d", &n,&m);
        for (int i=1;i<n;i++) {int u,v; scanf ("%d%d%s", &u,&v,str); Build (u,v,str[0]-' a ');
    Build (v,u,str[0]-' a '); } DFS1 (a);
    Ac.init ();
        for (int i=1;i<=m;i++) {int u,v; scanf ("%d%d", &u,&v); scanf ("%s", str); if (u==v) continue; 
        int Lca=getlca (U,V);
    KMP (U,v,lca,i);   
    } ac.getfail ();
    Ac.dfs (1);
    DFS2 (1,1,1);
    for (int i=1;i<=m;i++) printf ("%d\n", Ans[i]);
return 0; }

I was a little confused last night.

I did not write to the film has been handed, card a night evaluation, very sorry, thank you for not kill the grace.

The last found fault:
1. Calculate the time of the LCA Swap (U,U);
2.KMP Forget j=nxt[j];
3. Self-nxt[n] and Nx[n] two arrays confused.

Initially thought is doubled slowly, did not go to check the infinite cycle of the wrong, changed to a chain or T, just think is not where the writing hangs,
Long code must be static check the wrong + PAT.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.