zoukankan      html  css  js  c++  java
  • [NOI 2011] 阿狸的打字机

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=2434

    [算法]

            如果我们预处理出所有的字符串 , 显然是会空间超限的

            但是我们发现 , 该字符串集的字典树的节点树 <= 10 ^ 5

            不妨首先构建AC自动机

            考虑AC自动机的fail树  , 有性质 : 所有包含一个节点所代表字符串的节点一定是它的子树

       那么对于每个询问 , 我们就是要求出在fail树中x的子树中有多少个y

            不妨将询问离线 , DFS这棵字典树 , 用树状数组维护贡献

             时间复杂度 : O(NlogN)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int N = 2e5 + 10;
    const int ALPHA = 26;
    
    struct edge
    {
            int to , nxt;
    } e[N << 1];
    
    struct query
    {
            int l , r;
            int id;
    } ;
    
    int n , m , timer , tot;
    int ed[N] , l[N] , r[N] , head[N];
    vector< query > q[N];
    int ans[N];
    char s[N];
    
    struct Binary_Indexed_Tree
    {
            int c[N];
            inline int lowbit(int x)
            {
                    return x & (-x);
            }
            inline void modify(int x , int value)
            {
                    for (int i = x; i <= n; i += lowbit(i))
                            c[i] += value;
            }
            inline int query(int now)
            {
                    int ret = 0;
                    if (now < 0) return 0;
                    for (int i = now; i; i -= lowbit(i)) 
                            ret += c[i];
                    return ret; 
            }
            inline int query(int l , int r)
            {
                    return query(r) - query(l - 1);
            }
    } BIT;
    
    struct AC_Automaton
    {
            int sz , rt;
            int fail[N] , child[N][ALPHA] , fa[N];
            inline int new_node()
            {
                    ++sz;
                    fail[sz] = 0;
                    memset(child[sz] , 255 , sizeof(child[sz]));
                    return sz;
            }
            inline void init()
            {
                    sz = 0;
                    rt = new_node();
            }    
            inline void addedge(int u , int v)
            {
                    ++tot;
                    e[tot] = (edge){v , head[u]};
                    head[u] = tot;
            }
            inline void rebuild()
            {
                    queue< int > que;
                    fail[rt] = rt;
                    for (int ch = 0; ch < ALPHA; ch++)
                    {
                            if (child[rt][ch] == -1) 
                                    child[rt][ch] = rt;
                            else
                            {
                                    fail[child[rt][ch]] = rt;
                                    que.push(child[rt][ch]);
                            }
                    }
                    while (!que.empty())
                    {
                            int now = que.front();
                            que.pop();
                            for (int ch = 0; ch < ALPHA; ch++)
                            {
                                    if (child[now][ch] == -1)
                                            child[now][ch] = child[fail[now]][ch];
                                    else
                                    {
                                            fail[child[now][ch]] = child[fail[now]][ch];
                                            que.push(child[now][ch]);
                                    }
                            }
                    }
            }
            inline void dfs(int u , int father)
            {
                    l[u] = ++timer;
                    for (int i = head[u]; i; i = e[i].nxt)
                    {
                            int v = e[i].to;
                            if (v != father && v != u) dfs(v , u);
                    }
                    r[u] = timer;
            }
            inline void getfail()
            {
                    for (int i = 1; i <= sz; i++)    
                            addedge(fail[i] , i); 
                    dfs(rt , 0);
            }
            inline void calc(int u , int father)
            {
                    BIT.modify(l[u] , 1);
                    for (unsigned i = 0; i < q[u].size(); i++)
                            ans[q[u][i].id] = BIT.query(q[u][i].l , q[u][i].r);
                    for (int i = 0; i < ALPHA; i++)
                    {
                            if (fa[child[u][i]] == u)
                                    calc(child[u][i] , u);
                    }
                    BIT.modify(l[u] , -1);
            }
    } ACAM;
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    
    int main()
    {
            
            scanf("%s" , s + 1);
            n = strlen(s + 1);
            ACAM.init();
            int now = ACAM.rt , cnt = 1;
            s[++n] = 'P';
            for (int i = 1; i <= n; i++)
            {
                    if (s[i] == 'B') now = ACAM.fa[now];
                    else if (s[i] == 'P') 
                    {
                            ed[cnt] = now;
                            ++cnt;
                            continue;
                    } else 
                    {
                            if (ACAM.child[now][s[i] - 'a'] != -1) now = ACAM.child[now][s[i] - 'a'];
                            else 
                            {
                                    ACAM.child[now][s[i] - 'a'] = ACAM.new_node();
                                    ACAM.fa[ACAM.sz] = now;
                                    now = ACAM.child[now][s[i] - 'a'];
                            }
                    }
            }
            ACAM.rebuild();
            ACAM.getfail();
            scanf("%d" , &m);
            for (int i = 1; i <= m; i++)
            {
                    int x , y;
                    read(x); read(y);
                    q[ed[y]].push_back((query){l[ed[x]] , r[ed[x]] , i});
            }
            ACAM.calc(1 , 0);
            for (int i = 1; i <= m; i++) printf("%d
    " , ans[i]);
            
            return 0;
        
    }
  • 相关阅读:
    LeetCode 275. H-Index II
    LeetCode 274. H-Index
    LeetCode Gray Code
    LeetCode 260. Single Number III
    LeetCode Word Pattern
    LeetCode Nim Game
    LeetCode 128. Longest Consecutive Sequence
    LeetCode 208. Implement Trie (Prefix Tree)
    LeetCode 130. Surrounded Regions
    LeetCode 200. Number of Islands
  • 原文地址:https://www.cnblogs.com/evenbao/p/10459690.html
Copyright © 2011-2022 走看看