CF1207G Indie Album

Topic Link

problem

There \ (n-\) string, for the first \ (I \) string of a given by the following two ways.

  1. \ (. 1 \; C \) , which contains only a character string \ (C \) .

  2. \ (2 \ X \ C \) , the string of \ (x (1 \ le x <i) \) is added at the end of a character string \ (C \) to give.

There \ (m \) times asked each time a given query string \ (S \) and the position number \ (X \) , the first asked \ (X \) string, the string \ (S \) there have been several.

solution

You need to use \ (AC \) automata, Fenwick tree, \ (the DFS \) sequence.

First off down the inquiry, set up a string of all inquiries for the \ (AC \) automatic machine, thereby obtaining \ (fail \) tree. Then using \ (Fail \) Nature tree: the number of occurrence of a string in the letter string as the letter string run on AC automaton again and go to the right position +1 values, corresponding to the character string \ ( fail \) subtree weights and nodes.

There is a problem to be solved, if the letter string on the AC automatic machine run, run if violence is clearly not. So we find that he gives it (n \) \ ways string is also a tree form. So we can run in the following manner.

dfs(u,p) {//u为当前节点,p为其父亲在AC自动机上所跑到的节点
    将p移向u在AC自动机上跑到的节点
    将p所对应的的节点权值+1
    for(v是u的儿子) dfs(v,p)
    统计所有对于u这个串的查询的答案。
    将p所对应的节点权值-1
}

Found by the above way, we can ensure that only the query string every time the query in \ (AC \) generates a contribution to the automaton.

In \ (fail \) tree tree weights and sub-queries, you can use \ (dfs \) sequence + Fenwick tree is complete.

code

//@Author: wxyww
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
#include<cmath>
#include<map>
#include<string>
using namespace std;
typedef long long ll;
const int N =  400010;
ll read() {
    ll x = 0,f = 1; char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0',c = getchar();}
    return x * f;
}
char ss[N],s[N];
int fail[N],trie[N][30];
struct node {
    int v,nxt;
}e[N];
int idtot,siz[N],tree[N],fa[N],bh[N],ans[N],head[N],ejs,tot;
void add(int u,int v) {
    e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;
}
vector<pair<int,int> >que[N];
void update(int pos,int c) {
    while(pos <= idtot) {
        tree[pos] += c;
        pos += pos & -pos;
    }
}
int query(int pos) {
    int ret = 0;
    while(pos) {
        ret += tree[pos];
        pos -= pos & -pos;
    }
    return ret;
}
int add(char *t) {
    int n = strlen(t + 1),p = 0;
    for(int i = 1;i <= n;++i) {
        if(!trie[p][t[i] - 'a']) trie[p][t[i] - 'a'] = ++tot;
        p = trie[p][t[i] - 'a'];
    }
    // printf("!!!%d\n",p);
    return p;
}
queue<int>q;
vector<int>E[N];
void build() {
    for(int i = 0;i < 26;++i) if(trie[0][i]) q.push(trie[0][i]);

    while(!q.empty()) {
        int u = q.front();q.pop();
        E[fail[u]].push_back(u);
        for(int i = 0;i < 26;++i) {
            if(!trie[u][i]) trie[u][i] = trie[fail[u]][i];
            else fail[trie[u][i]] = trie[fail[u]][i],q.push(trie[u][i]);
        }
    }
}
void AC_dfs(int u) {
    int k = E[u].size();
    bh[u] = ++idtot;siz[u] = 1;
    for(int i = 0;i < k;++i) {
        int v = E[u][i];
        AC_dfs(v);
        siz[u] += siz[v];
    }
}
int getans(int p) {
    // printf("!!!%d %d\n",bh[p] + siz[p] - 1,bh[p]);
    return query(bh[p] + siz[p] - 1) - query(bh[p] - 1);
}
void dfs(int u,int p) {
    p = trie[p][s[u] - 'a'];
    // if(u == 2) printf("!!!%d\n",u);
    
    update(bh[p],1);
    // printf("!!%d %d\n",u,s[u] - 'a');
    // printf("!!!%d %d\n",u,p);
    for(int i = head[u];i;i = e[i].nxt) dfs(e[i].v,p);
    
    int k = que[u].size();
    for(int i = 0;i < k;++i) ans[que[u][i].second] = getans(que[u][i].first);

    update(bh[p],-1);

}
int main() {
    int n = read();
    for(int i = 1;i <= n;++i) {
        int opt = read();
        if(opt == 2) fa[i] = read();
        add(fa[i],i);
        // cin>>s[i];
        scanf("%s",&s[i]);
    }

    int m = read();
    for(int i = 1;i <= m;++i) {
        int id = read();
        scanf("%s",ss + 1);
        que[id].push_back(make_pair(add(ss),i));
    }

    build();

    // for(int i = 0;i < 26;++i) printf("!!%d\n",trie[0][i]);

    // for(int i = 1;i <= tot;++i) printf("!!%d\n",fail[i]);

    // printf("!!%d\n",trie[1][0]);

    AC_dfs(0);

    // printf("!!!%d %d\n",tot,idtot);

    for(int i = 1;i <= n;++i) if(!fa[i]) dfs(i,0);

    

    for(int i = 1;i <= m;++i) printf("%d\n",ans[i]);

    return 0;
}

Guess you like

Origin www.cnblogs.com/wxyww/p/CF1207G.html