• BZOJ2434 [NOI2011] 阿狸的打字机 【树链剖分】【线段树】【fail树】【AC自动机】


    题目分析:

    画一下fail树,就会发现就是x的子树中属于y路径的,把y剖分一下,用线段树处理

    $O(n*log^2 n)$。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int maxn = 102000;
      5 
      6 string str;
      7 struct node{int ch[26],fail,fa;}T[maxn];
      8 int star[maxn],ans[maxn],num = 1,snum,m;
      9 int dfsin[maxn],dfsout[maxn],poss[maxn]; // failtree
     10 int Tnb[maxn],top[maxn],sz[maxn];
     11 vector <int> g[maxn];
     12 vector<pair<int,int> > Qy[maxn];
     13 
     14 void read(){
     15     ios::sync_with_stdio(false);
     16     cin.tie(0);
     17     cin >> str;
     18     int now = 1;
     19     for(int i=0;i<str.length();i++){
     20     if(str[i] == 'B') now = T[now].fa;
     21     else if(str[i] == 'P') star[++snum] = now;
     22     else{
     23         if(T[now].ch[str[i]-'a']) now = T[now].ch[str[i]-'a'];
     24         else{
     25         T[now].ch[str[i]-'a'] = ++num;
     26         T[num].fa = now;
     27         now = num;
     28         }
     29     }
     30     }
     31     snum = 0;
     32 }
     33 
     34 void dfs(int now){
     35     dfsin[now] = dfsout[now] = ++snum;
     36     poss[snum] = now;
     37     for(int i=0;i<g[now].size();i++){
     38     dfs(g[now][i]);
     39     dfsout[now] = dfsout[g[now][i]];
     40     }
     41 }
     42 
     43 queue<int> q;
     44 void BuildACAutomaton(){
     45     q.push(1);T[1].fail = 1;
     46     while(!q.empty()){
     47     int k = q.front();q.pop();
     48     for(int i=0;i<26;i++){
     49         if(T[k].ch[i] == 0) continue;
     50         int ff = T[k].fail;
     51         while(ff != 1 && T[ff].ch[i] == 0) ff = T[ff].fail;
     52         if(T[ff].ch[i]==T[k].ch[i]||T[ff].ch[i]==0)T[T[k].ch[i]].fail=1;
     53         else T[T[k].ch[i]].fail = T[ff].ch[i];
     54         q.push(T[k].ch[i]);
     55         g[T[T[k].ch[i]].fail].push_back(T[k].ch[i]);
     56     }
     57     }
     58     snum = 0; dfs(1); snum = 0;
     59 }
     60 
     61 int QT[maxn*4];
     62 
     63 void Add(int now,int tl,int tr,int pos){
     64     if(tl == tr){QT[now]++;return;}
     65     int mid = (tl+tr)/2;QT[now]++;
     66     if(mid >= pos) Add(now<<1,tl,mid,pos);
     67     else Add(now<<1|1,mid+1,tr,pos);
     68 }
     69 int Query(int now,int tl,int tr,int l,int r){
     70     if(tl >= l && tr <= r) return QT[now];
     71     if(tl > r || tr < l) return 0;
     72     int mid = (tl+tr)/2;
     73     return Query(now<<1,tl,mid,l,r)+Query(now<<1|1,mid+1,tr,l,r);
     74 }
     75 
     76 void dfsmiao(int now){
     77     for(int i=0;i<26;i++){
     78     if(T[now].ch[i]==0)continue;
     79     dfsmiao(T[now].ch[i]);
     80     sz[now] += sz[T[now].ch[i]];
     81     }
     82     sz[now]++;
     83 }
     84 
     85 void dfsyeah(int now,int tp){
     86     int son = 0;top[now] = tp;Tnb[now] = ++snum;
     87     for(int i=0;i<26;i++){
     88     if(sz[T[now].ch[i]] > sz[son]) son = T[now].ch[i];
     89     }
     90     if(son) dfsyeah(son,tp);
     91     for(int i=0;i<26;i++){
     92     if(T[now].ch[i] == 0 || T[now].ch[i] == son) continue;
     93     dfsyeah(T[now].ch[i],T[now].ch[i]);
     94     }
     95 }
     96 
     97 void treechain(){
     98     dfsmiao(1);
     99     dfsyeah(1,1);
    100 }
    101 
    102 void readquery(){
    103     cin >> m;
    104     for(int i=1;i<=m;i++){
    105     int x,y; cin >> x >> y;
    106     x = star[x];y = star[y];
    107     Qy[poss[dfsin[x]-1]].push_back(make_pair(y,i));
    108     Qy[poss[dfsout[x]]].push_back(make_pair(y,i));
    109     }
    110 }
    111 
    112 void solve(int endpos,int now){
    113     if(ans[now]) ans[now] = -ans[now];
    114     while(endpos){
    115     ans[now] += Query(1,1,num,Tnb[top[endpos]],Tnb[endpos]);
    116     endpos = T[top[endpos]].fa;
    117     }
    118 }
    119 
    120 void work(){
    121     for(int i=1;i<=num;i++){
    122     int now = poss[i];
    123     Add(1,1,num,Tnb[now]);
    124     for(int j=0;j<Qy[now].size();j++){
    125         solve(Qy[now][j].first,Qy[now][j].second);
    126     }
    127     }
    128     for(int i=1;i<=m;i++) cout<<ans[i]<<endl;
    129 }
    130 
    131 int main(){
    132     //freopen("7.in","r",stdin);
    133     read();
    134     treechain();
    135     BuildACAutomaton();
    136     readquery();
    137     work();
    138     return 0;
    139 }
  • 相关阅读:
    vue2.0动态添加组件
    Kali Linux信息收集工具全
    Kali Linux 弱点分析工具全集
    如何DIY一个简单的反弹Shell脚本
    深入理解DIP、IoC、DI以及IoC容器
    Intellij IDEA常用配置详解
    GIT 的常规操作
    Nodejs学习笔记(一)--- 简介及安装Node.js开发环境
    什么是“对用户友好”
    Facebook为什么使用PHP编程语言?
  • 原文地址:https://www.cnblogs.com/Menhera/p/10222057.html
Copyright © 2020-2023  润新知