zoukankan      html  css  js  c++  java
  • bzoj 2434 [NOI2011] 阿狸的打字机

    题面:

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

    题解:

    建立AC自动机

    把fail树拎出来,询问(x,y)就是在root到y的路径上,沿着fail能走到x的点有几个

    那么就是fail树上x的子树中有几个root到y路径上的节点

    我们遍历fail树,可以得到每个节点的进出时间l,r

    然后遍历trie树,进入一个节点就在树状数组上这个节点的l值的位置+1,退出时就-1,当前节点如果是某一个字符串的end时,我们处理所有y是这个字符串的询问:

    我们只要看子树里的和就行了,那么就查询l到r的和就是答案

    Code:

      1 #include<stdio.h>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<algorithm>
      5 #include<vector>
      6 #include<map>
      7 #include<set>
      8 #include<cmath>
      9 #include<iostream>
     10 #include<queue>
     11 #include<string>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,int> pii;
     15 typedef long double ld;
     16 typedef unsigned long long ull;
     17 typedef pair<long long,long long> pll;
     18 #define fi first
     19 #define se second
     20 #define pb push_back
     21 #define mp make_pair
     22 #define rep(i,j,k)  for(register int i=(int)(j);i<=(int)(k);i++)
     23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--)
     24 
     25 ll read(){
     26     ll x=0,f=1;char c=getchar();
     27     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
     28     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
     29     return x*f;
     30 }
     31 
     32 const int maxnode=150100;
     33 const int maxn=100100;
     34 
     35 #define lowbit(x) (x&-x)
     36 struct BIT{
     37     int a[maxn*5];
     38     void add(int x,int val){
     39         while(x<=maxn*4){
     40             a[x]+=val;
     41             x+=lowbit(x);
     42         }
     43     }
     44     int ask(int x){
     45         int ret=0;
     46         while(x){ret+=a[x];x-=lowbit(x);}
     47         return ret;
     48     }
     49 } bit;
     50 
     51 vector<pii> q[maxn];
     52 string s;
     53 int l[maxn],r[maxn],tim;
     54 int ans[maxn];
     55 int dy[maxn*4];
     56 int head[maxn*4],to[maxn*8],nxt[maxn*8],cnt;
     57 int nums;
     58 
     59 void addedge(int a,int b){
     60      to[++cnt]=b;nxt[cnt]=head[a];head[a]=cnt;
     61 }
     62 
     63 struct Trie{
     64     int nxt[maxnode][26],fail[maxnode],en[maxnode];
     65     int root,sz;
     66     int fa[maxnode];
     67     int nxt2[maxnode][26];
     68     
     69     int newnode(){
     70         for(int i=0;i<26;i++) nxt[sz][i]=-1;
     71         en[sz]=0;sz++;
     72         return sz-1;
     73     }
     74     void init(){
     75         sz=0;
     76         root=newnode();
     77     }
     78     
     79     void doit(){
     80         getline(cin,s);
     81         int nw=root;
     82         for(int i=0;i<s.size();i++){
     83             if(s[i]=='P') en[nw]=++nums,dy[nums]=nw;
     84             else if(s[i]=='B') nw=fa[nw];
     85             else{
     86                 if(nxt[nw][s[i]-'a']==-1) nxt[nw][s[i]-'a']=newnode();
     87                 fa[nxt[nw][s[i]-'a']]=nw;
     88                 nw=nxt[nw][s[i]-'a'];
     89             }
     90         }
     91     }            
     92     void build(){
     93         for(int i=0;i<sz;i++)
     94             for(int j=0;j<26;j++)
     95                 nxt2[i][j]=nxt[i][j];
     96         queue<int> q;
     97         fail[root]=root;
     98         for(int i=0;i<26;i++)
     99             if(nxt[root][i]==-1) nxt[root][i]=root;
    100             else{
    101                 fail[nxt[root][i]]=root;
    102                 q.push(nxt[root][i]);
    103             }
    104         while(!q.empty()){
    105             int nw=q.front();q.pop();
    106             for(int i=0;i<26;i++)
    107                 if(nxt[nw][i]==-1) nxt[nw][i]=nxt[fail[nw]][i];
    108                 else{
    109                     if(nxt[nw][i]==0){
    110                         cout<<nw<<endl;
    111                         break;
    112                     }
    113                     fail[nxt[nw][i]]=nxt[fail[nw]][i];
    114                     q.push(nxt[nw][i]);
    115                 }
    116         }
    117         for(int i=1;i<sz;i++){
    118             int u=i,v=fail[u];
    119             addedge(v,u);
    120         }
    121     }
    122     
    123     void dfs(int u){
    124         bit.add(l[u],1);
    125         if(en[u]){
    126             for(int i=0;i<q[en[u]].size();i++){
    127                 int v=q[en[u]][i].fi;v=dy[v];
    128                 int ind=q[en[u]][i].se;
    129                 ans[ind]=bit.ask(r[v])-bit.ask(l[v]-1);
    130             }
    131         }
    132         for(int i=0;i<26;i++)
    133             if(nxt2[u][i]!=-1) dfs(nxt2[u][i]);
    134         bit.add(l[u],-1);
    135     }
    136 } tr;
    137 
    138 inline void dfs(int u){
    139     l[u]=++tim;
    140     r[u]=l[u];
    141     for(int i=head[u];i;i=nxt[i]){
    142         int v=to[i];
    143         dfs(v);
    144         r[u]=r[v];
    145     }
    146 }
    147 
    148 int main(){
    149 //    freopen("2434.in","r",stdin);
    150 //    freopen("2434.out","w",stdout);
    151     tr.init();
    152     tr.doit();
    153     tr.build();
    154     int m=read();
    155     for(int i=1;i<=m;i++){
    156         int x=read(),y=read();
    157         q[y].pb(mp(x,i));
    158     }
    159     dfs(0);
    160     tr.dfs(0);
    161     for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    162     return 0;
    163 }
    164 
    165 /*
    166 aPaPBbP
    167 3
    168 1 2
    169 1 3
    170 2 3
    171 */
    View Code

    Review:

    1. 卡了几个月的问题:输入超时

      我们不能维护一个字符串表示当前打字机内的字符串,然后每次暴力插入,这样就超时了

      我们应该维护一个当前在trie上的节点,然后来回移动

    2. 怎么想:

      其实不难想

      首先肯定上AC自动机,然后询问肯定得离线,那么就是求子树内的和,用dfs序转化成序列上的和是常规套路了

  • 相关阅读:
    团队项目-选题报告
    第一次结对编程作业
    第一次个人编程作业
    第一次博客作业
    Java web的读取Excel简单Demo
    Java一些常见的出错异常处理
    JSTL截取字符串
    DATAX动态参数数据传递
    DataX实现oracle到oracle之间的数据传递
    DataX安装环境搭建
  • 原文地址:https://www.cnblogs.com/wawawa8/p/9539358.html
Copyright © 2011-2022 走看看