首页 > 其他分享 >[NOI2011] 阿狸的打字机

[NOI2011] 阿狸的打字机

时间:2023-04-17 16:26:15浏览次数:52  
标签:阿狸 int void fa 打字机 NOI2011 fail now

[NOI2011] 阿狸的打字机

/*
其实也就是动态建树的问题,如果这个点有,那就把这个点给激活。
如果这个点消失了,对应的把他的值取消掉就可以了
这样就可以在对应的树下进行查询。

然后就是单点修改,对树的子树大小进行查询,用树状数组进行维护就可以了

首先根据fail建立子树
在fail树上查找某个串出现的次数,其实也就是子树的大小就可以了


*/

#include <bits/stdc++.h>
using namespace std;
const int M=2e5+5;

char s[M];
int n,m;
int idx[M],cnt=0;
int fa[M],ch[M][26],fail[M],tot;

void init_tire() {//建立tire树
    scanf("%s",s+1);
    n=strlen(s+1);
    int p=0;
    for(int i=1;i<=n;i++) {
        if(s[i]=='P')idx[++cnt]=p;
        else if(s[i]=='B')p=fa[p];
        else {
            int v=s[i]-'a';
            if(ch[p][v]==0)ch[p][v]=++tot,fa[ch[p][v]]=p;
            p=ch[p][v];
        }
    }
}

void build() {
    queue<int>q;
    for(int i=0;i<26;i++)
        if(ch[0][i])q.push(ch[0][i]);
    while(!q.empty()) {
        int now=q.front();q.pop();
        for(int i=0;i<26;i++) {
            if(ch[now][i]) {
                fail[ch[now][i]]=ch[fail[now]][i];
                q.push(ch[now][i]);
            }
            else ch[now][i]=ch[fail[now]][i];
        }
    }
}

int lowbit(int x) {
    return x&-x;
}


int L[M],R[M],id=0;
vector<int>g[M];
void dfs(int now,int fa) {
    L[now]=++id;
    for(auto to:g[now])
        if(to!=fa)dfs(to,now);
    R[now]=id;
}

int c[M];
void add(int i,int v) {
    while(i<=id) {
        c[i]+=v;
        i+=lowbit(i);
    }
}

int query(int i) {
    int ans=0;
    while(i) {
        ans+=c[i];
        i-=lowbit(i);
    }
    return ans;
}

#define fi first
#define se second

int ans[M];
vector<int>v[M];
pair<int,int>q[M];
void solve() {
    int m;cin>>m;
    for(int i=1;i<=m;i++) {
        cin>>q[i].fi>>q[i].se;
        v[q[i].se].push_back(i);
    }
    for(int i=0;i<=tot;i++)g[fail[i]].push_back(i);
    dfs(0,0);
    int p=0,cnt=0;
    for(int i=1;i<=n;i++) {
        if(s[i]=='P') {
            cnt++;
            for(auto j:v[cnt]) {
                int x=idx[q[j].fi];
                ans[j]=query(R[x])-query(L[x]-1);
            }
        }
        else if(s[i]=='B')add(L[p],-1),p=fa[p];
        else p=ch[p][s[i]-'a'],add(L[p],1);
    }
    for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';
}

int main() {
    init_tire();
    build();
    solve();
    return 0;
}

标签:阿狸,int,void,fa,打字机,NOI2011,fail,now
From: https://www.cnblogs.com/basicecho/p/17326217.html

相关文章

  • 【洛谷】P2414 [NOI2011] 阿狸的打字机(AC自动机+离线询问)
    原题链接题意给定\(n\)个字符串,\(m\)次询问一个字符串\(x\)在另一个字符串\(y\)的出现次数。\(1\leqn,m\leq10^5\)。思路要解决多个字符串的问题,不难想到......
  • TimeLine实现打字机
    首先创建timeLine并创建ctrl轨道  代码奉上=================》usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.......
  • P3213 [HNOI2011]勾股定理 题解
    据说是NP问题。很明显我们要先预处理出来勾股数对。但由于数过于大,所以常规的枚举是解决不了问题的。但也貌似没有什么很好的办法可以立马找到一个数的勾股数对。所以......
  • P3215 [HNOI2011]括号修复题解
    发现题解里的维护前后缀最大最小值的做法都是感性理解,所以我就来写个证明。将(看做\(-1\),)看做\(1\),首先几个变量:\(n\)代表括号序列的长度。\(a_i\)代表前缀和......
  • luogu P1971 [NOI2011] 兔兔与蛋蛋游戏
    题面传送门没想到二分图博弈这么早就考了?首先我们发现,如果将和起点行列之和奇偶性一样的点设为黑色,其余设为白色,那么每次空格只会在异色边之间走,而不会在同色边之间走。......
  • [oeasy]python0037_终端_terminal_电传打字机_tty_shell_控制台_console_发展历史
    换行回车回忆上次内容​换行​​和​​回车​​是两回事​换行​对应字节​​0x0A​​Line-Feed水平不动垂直向上喂纸所以是​​feed​​​回车​对应字节​​0x0D......
  • [oeasy]python0037_终端_terminal_电传打字机_tty_shell_控制台_console_发展历史
    换行回车回忆上次内容换行和回车是两回事换行对应字节0x0ALine-Feed水平不动垂直向上喂纸所以是feed回车对应字节0x0DCarriage-Return垂直......
  • [oeasy]python0037_电传打字机_打印头_print_head_carriage_词源
    换行回车回忆上次内容上次我们diy了自己的小动物还可以让小动物变色、报时还可以说些话这很亚文化很酷炫的亚文化不是吗?回忆一下最开始研究报时......
  • 打字机
    <!DOCTYPEhtml><html><head><metacharset="utf-8"><title></title><linkrel="stylesheet"href="new_file.css"></head><......
  • 【题解】P1973 [NOI2011] NOI 嘉年华
    yyc学长说是典题,就记一下。题意给出\(n\)个区间,试在丢弃一些区间后,把区间分成两部分,使得不存在同时被两部分中的区间覆盖的位置,求:最终包含区间数较小的部分的区间......