[COCI2015] Divljak - AC automaton, the DFS sequence, Fenwick tree, the LCA

There \ (n-\) a query string \ (S_i \) , there is an initially empty set of character strings \ (T \) , followed with a \ (Q \) operations, each time a character string is added to the collection or given \ (x \) asked how many collection string contains \ (S_x \)

Solution

Consider \ (S_i \) establish ACAM, to build a \ (fail \) tree, a match point occurs, you need to modify it to the root of the chain, is asking a query point value

This requires split tree chain, we can look at the difference, so every change is a point of asking is a sub-tree and

So we determined \ (Fail \) the DFS tree sequence, a maintenance tree array, each modification, the input string is run on ACAM thrown, all the nodes on the matching \ (1 + \) , where the need open tag array, to prevent the same input string to the same node multiple \ (1 + \)

At each interrogation, to output \ (S_x \) subtree and to the corresponding subtree

It is clear that the above solution is wrong!

While we ensure that for each query string, we only played once labeled the same node, but the prefix and the results will still go back to repeat

So we need another way to solve this problem and path

On the basis of the above solution , considering all points labeled played out according to \ (DFS \) sequence ordering, adjacent nodes \ (LCA \) position \ (- 1 \) to

#include <bits/stdc++.h>
using namespace std;

const int N = 2000005;

int ar[N];
int lowbit(int t) {
    return t & (-t);
}
void add(int i, int v) {
    if(i==0) return;
    for (; i < N; ar[i] += v, i += lowbit(i));
}
int sum(int i) {
    int s = 0;
    for (; i > 0; s += ar[i], i -= lowbit(i));
    return s;
}
int sum(int p,int q) {
    return sum(q)-sum(p-1);
}

int dfn[N],idfn[N],fin[N],dep[N],fa[N][21];

int lca(int p,int q) {
    if(dep[p]<dep[q]) swap(p,q);
    for(int i=20;i>=0;--i) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i];
    for(int i=20;i>=0;--i) if(fa[p][i]-fa[q][i]) p=fa[p][i],q=fa[q][i];
    if(p==q) return p;
    else return fa[p][0];
}

struct ACA {
    queue <int> q;
    int c[N][26],val[N],fi[N],cnt,ans[1005];
    void init() {
        memset(c,0,sizeof c);
        memset(val,0,sizeof val);
        memset(fi,0,sizeof fi);
        memset(ans,0,sizeof ans);
        cnt=0;
    }
    int ins(char *str,int id) {
        int len=strlen(str), p=0;
        for(int i=0; i<len; i++) {
            int v=str[i]-'a';
            if(!c[p][v]) c[p][v]=++cnt;
            p=c[p][v];
        }
        val[p]=id;
        return p;
    }
    void build() {
        for(int i=0; i<26; i++) if(c[0][i]) fi[c[0][i]]=0, q.push(c[0][i]);
        while(!q.empty()) {
            int u=q.front();
            q.pop();
            for(int i=0; i<26; i++)
                if(c[u][i]) fi[c[u][i]]=c[fi[u]][i], q.push(c[u][i]);
                else c[u][i]=c[fi[u]][i];
        }
    }
    void query(char *s) {
        set<int> st;
        int len=strlen(s);
        int p=0;
        for(int i=0; i<len; i++) {
            p=c[p][s[i]-'a'];
            if(p&&st.find(dfn[p])==st.end()) {
                st.insert(dfn[p]);
                add(dfn[p],1);
            }
        }
        vector <int> vec;
        for(auto i=st.begin();i!=st.end();i++) vec.push_back(*i);
        for(int i=1;i<vec.size();i++) {
            add(dfn[lca(idfn[vec[i]],idfn[vec[i-1]])],-1);
        }
    }
} acam;

vector<int> g[N];
int n,q,endid[N],ind;
char str[N];

void dfs(int p) {
    dfn[p]=++ind; idfn[ind]=p;
    for(int q:g[p]) fa[q][0]=p, dep[q]=dep[p]+1, dfs(q);
    fin[p]=ind;
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1; i<=n; i++) {
        cin>>str;
        endid[i]=acam.ins(str,i);
    }
    acam.build();
    for(int i=1; i<=acam.cnt; i++) g[acam.fi[i]].push_back(i);
    dfs(0);
    for(int j=1;j<=20;j++) {
        for(int i=1;i<=acam.cnt;i++) {
            fa[i][j]=fa[fa[i][j-1]][j-1];
        }
    }
    cin>>q;
    for(int i=1; i<=q; i++) {
        int t1,t2;
        cin>>t1;
        if(t1==1) {
            cin>>str;
            acam.query(str);
        } else {
            cin>>t2;
            cout<<sum(dfn[endid[t2]],fin[endid[t2]])<<endl;
        }
    }
}

Guess you like

Origin www.cnblogs.com/mollnn/p/12443298.html