bzoj 2434 阿狸的打字机 - Aho-Corasick自动机 - 树状数组

题目传送门

  传送站I

  传送站II

题目大意

  阿狸有一个打字机,它有3种键:

  1. 向缓冲区追加小写字母
  2. P:打印当前缓冲区(缓冲区不变)
  3. B:删除缓冲区中最后一个字符

  然后多次询问第$x$个被打印出来的串在第$y$个被打印出来的串中出现多少次。

  每次查询相当于询问串$x$的结束节点在fail树中的子树包含多少串$y$的点。

  又因为这些串的构造比较另类。所以考虑把询问离线,然后用树状数组维护子树中关键点的个数。

Code

  1 /**
  2  * bzoj
  3  * Problem#2434
  4  * Accepted
  5  * Time: 620ms
  6  * Memory: 17792k
  7  */
  8 #include <algorithm>
  9 #include <iostream>
 10 #include <cstdlib>
 11 #include <cstdio>
 12 #include <vector>
 13 #include <queue>
 14 #include <stack>
 15 using namespace std;
 16 typedef bool boolean;
 17 
 18 const int N = 1e5 + 5;
 19 
 20 typedef class IndexedTree {
 21     public:
 22         int s;
 23         int ar[N];
 24 
 25         void add(int idx, int val) {
 26             for ( ; idx <= s; idx += (idx & (-idx)))
 27                 ar[idx] += val;
 28         }
 29 
 30         int getSum(int idx) {
 31             int rt = 0;
 32             for ( ; idx; idx -= (idx & (-idx)))
 33                 rt += ar[idx];
 34             return rt;
 35         }
 36 }IndexedTree;
 37 
 38 typedef class TrieNode {
 39     public:
 40         int in, out;
 41         TrieNode* ch[26];
 42         TrieNode* fail;
 43 }TrieNode;
 44 
 45 TrieNode pool[N];
 46 TrieNode *top = pool;
 47 
 48 TrieNode* newnode() {
 49     return ++top;
 50 }
 51 
 52 typedef class AhoCorasick {
 53     public:
 54         TrieNode *rt;
 55 
 56         AhoCorasick():rt(newnode()) {    }
 57 
 58         void travel(char* str, TrieNode** ts) {
 59             stack<TrieNode*> s;
 60             TrieNode* p;
 61             s.push(rt);
 62             for (int i = 0, c, cp = 0; str[i]; i++) {
 63                 if (str[i] == 'B')
 64                     s.pop();
 65                 else if (str[i] == 'P')
 66                     ts[++cp] = s.top();
 67                 else {
 68                     p = s.top(), c = str[i] - 'a';
 69                     if (!p->ch[c])
 70                         p->ch[c] = newnode();
 71                     s.push(p->ch[c]);
 72                 }
 73             }
 74         }
 75 
 76         void build(vector<int> *g) {
 77             queue<TrieNode*> que;
 78             que.push(rt);
 79             while (!que.empty()) {
 80                 TrieNode* p = que.front();
 81                 que.pop();
 82                 for (int i = 0; i < 26; i++) {
 83                     TrieNode *np = p->ch[i], *f = p->fail;
 84                     if (!np)    continue;
 85                     while (f && !f->ch[i])    f = f->fail;
 86                     if (!f)
 87                         np->fail = rt;
 88                     else
 89                         np->fail = f->ch[i];
 90                     que.push(np);
 91                 }
 92             }
 93             for (TrieNode* p = top; p != pool + 1; p--)
 94                 g[p->fail - pool].push_back(p - pool);
 95         }
 96 }AhoCorasick;
 97 
 98 typedef class Query {
 99     public:
100         int x, y, id;
101 
102         boolean operator < (Query b) const {
103             return y < b.y;
104         }
105 }Query;
106 
107 int m, cnt = 0;
108 char str[N];
109 int *res;
110 Query *qs;
111 TrieNode** ts;
112 vector<int> g[N];
113 IndexedTree it;
114 AhoCorasick ac;
115 
116 inline void init() {
117     gets(str);
118     scanf("%d", &m);
119     qs = new Query[(m + 1)];
120     res = new int[(m + 1)];
121     ts = new TrieNode*[(m + 1)];
122     for (int i = 1; i <= m; i++) {
123         scanf("%d%d", &qs[i].x, &qs[i].y);
124         qs[i].id = i;
125     }
126 }
127 
128 void dfs(int p) {
129     pool[p].in = ++cnt;
130     for (int i = 0; i < (signed) g[p].size(); i++)
131         dfs(g[p][i]);
132     pool[p].out = cnt;
133 }
134 
135 inline void solve() {
136     ac.travel(str, ts);
137     ac.build(g);
138     it.s = (top - pool + 1);
139     dfs(1);
140     sort(qs + 1, qs + m + 1);
141     stack<TrieNode*> s;
142     s.push(ac.rt);
143     for (int i = 0, cur = 0, cq = 1; cq <= m && str[i]; i++) {
144         TrieNode *p = s.top();
145         if (str[i] == 'B') {
146             it.add(p->in, -1);
147             s.pop();
148         } else if (str[i] == 'P') {
149             cur++;
150             while (cq <= m && qs[cq].y == cur)
151                 res[qs[cq].id] = it.getSum(ts[qs[cq].x]->out) - it.getSum(ts[qs[cq].x]->in - 1), cq++;
152         } else {
153             p = p->ch[str[i] - 'a'];
154             it.add(p->in, 1);
155             s.push(p);
156         }
157     }
158     for (int i = 1; i <= m; i++)
159         printf("%d\n", res[i]);
160 }
161 
162 int main() {
163     init();
164     solve();
165     return 0;
166 }
posted @ 2018-03-24 20:24  阿波罗2003  阅读(196)  评论(0编辑  收藏  举报