• bzoj 2434: 阿狸的打字机 fail树+离线树状数组


    题目大意:

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

    题解:

    首先我们可以发现这个打字的过程本身就是在Trie上滚来滚去的过程
    所以我们可以直接根据这个建树
    然后构建出fail树后我们考虑如何处理询问
    对于任意一个询问(x,y)我们都可以统计从y到root的节点上有多少指向x的fail
    但是这样肯定超时
    所以反向考虑x的所有指向x的fail,和指向指向x的fail的fail... ...
    我们把所有的fail反响建出一颗树来
    这时候我们发现以x为根的子树即为所有直接或间接指向x的fail(反转前)
    所以我们统计一下这可子树中有多少y即可
    所以可以树套树解决
    我们发现我们可以直接离线树状数组瞎搞
    我们直接重复一遍打印的过程,把当前在凹槽中的字符对应的fail树的dfs序上+1
    离线询问后直接查询即可

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
        x=0;char ch;bool flag = false;
        while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
        while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const int maxn = 100010;
    int ch[maxn][26],nodecnt,fa[maxn];
    int val[maxn];
    char str[maxn];
    struct Edge{
        int to,next;
    }G[maxn];
    int head[maxn],cnt;
    void add(int u,int v){
        G[++cnt].to = v;
        G[cnt].next = head[u];
        head[u] = cnt;
    }
    int q[maxn],l,r,f[maxn];
    inline void build(){
        f[0] = 0;l = 0;r = -1;
        int u = 0;
        for(int c=0;c<26;++c){
            if(ch[u][c]){
                f[ch[u][c]] = 0;
                q[++r] = ch[u][c];
            }
        }
        while(l <= r){
            u = q[l++];
            for(int c=0;c<26;++c){
                int v = ch[u][c];
                if(!v){
                    ch[u][c] = ch[f[u]][c];
                    continue;
                }q[++r] = v;
                int x = f[u];
                while(x && !ch[x][c]) x = f[x];
                f[v] = ch[x][c];
            }
        }
    }
    int ind[maxn],oud[maxn],dfs_clock = -1;
    #define v G[i].to
    inline void dfs(int u){
        ind[u] = ++ dfs_clock;
        for(int i = head[u];i;i=G[i].next) dfs(v);
        oud[u] = dfs_clock;
    }
    #undef v
    struct Node{
        int x,y,id;
        bool friend operator < (const Node &a,const Node &b){
            return a.y < b.y;
        }
    }a[maxn];
    int anss[maxn];
    int c[maxn],num;
    #define lowbit(x) (x&-x)
    inline void modify(int x,int y){
        for(;x<=dfs_clock + 10;x += lowbit(x)) c[x] += y;
    }
    inline int query(int x){
        int ret = 0;
        for(;x;x-=lowbit(x)) ret += c[x];
        return ret;
    }
    int mp[maxn];
    int main(){
        scanf("%s",str);
        int n = strlen(str);
        int nw = 0;
        for(int i=0;i<n;++i){
            if(str[i] == 'P') val[nw] = ++num,mp[num] = nw;
            else if(str[i] == 'B') nw = fa[nw];
            else{
                int c = str[i] - 'a';
                if(ch[nw][c] == 0){
                    ch[nw][c] = ++nodecnt;
                    fa[nodecnt] = nw;
                }nw = ch[nw][c];
            }
        }build();
        for(int i=nodecnt;i>=1;--i) add(f[i],i);
        dfs(0);
        int m;read(m);
        for(int i=1;i<=m;++i){
            read(a[i].x);
            read(a[i].y);
            a[i].id = i;
        }sort(a+1,a+m+1);
        nw = 0;int p = 1,cnt_p = 0;
        for(int i=0;i<n;++i){
            if(str[i] == 'P'){
                ++ cnt_p;
                while(a[p].y == cnt_p){
                    anss[a[p].id] = query(oud[mp[a[p].x]])-query(ind[mp[a[p].x]]-1);
                    ++p;
                }
            }else if(str[i] == 'B'){
                modify(ind[nw],-1);
                nw = fa[nw];
            }else{
                int c = str[i] - 'a';
                nw = ch[nw][c];
                modify(ind[nw],1);
            }
        }
        for(int i=1;i<=m;++i) printf("%d
    ",anss[i]);
        getchar();getchar();
        return 0;
    }
    
  • 相关阅读:
    Contiki学习笔记  第一个程序:Hello World
    contiki学习笔记---process结构体
    MYSQL碰到The total number of locks exceeds the lock table size 问题解决记录
    navicat连接mysql查询结果中文都是?号(C#)
    C#使用OracleBulkCopy
    解决IIS应用程序池默认回收导致程序崩溃
    构建可读性更高的 ASP.NET Core 路由机制
    .Net(C#)汉字和Unicode编码互相转换
    聊聊c#字符串拼接
    VS2010到VS2019各个版本的密钥
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6493731.html
Copyright © 2020-2023  润新知