codevs 1946 阿狸的打字机

题目描述 Description

阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机 上只有 28 个按键,分别印有 26 个小写英文字母和'B'、'P'两个字母。 经阿狸研究发现,这个打字机是这样工作的:

 输入小写字母,打字机的一个凹槽中会加入这个字母(按 P 前凹槽中至 少有一个字母)。

 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。

 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并 换行,但凹槽中的字母不会消失(保证凹槽中至少有一个字母)。

例如,阿狸输入 aPaPBbP,纸上被打印的字符如下: a aa ab 我们把纸上打印出来的字符串从 1 开始顺序编号,一直到 n。打字机有一个 非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数 (x,y)(其中 1≤x,y≤n),打字机会显示第 x 个打印的字符串在第 y 个打印的字符串 中出现了多少次。 阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助 他么?

输入描述 Input Description

输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。 第二行包含一个整数 m,表示询问个数。 接下来 m 行描述所有由小键盘输入的询问。其中第 i 行包含两个整数 x, y, 表示第 i 个询问为(x, y)。

输出描述 Output Description

输出 m 行,其中第 i 行包含一个整数,表示第 i 个询问的答案。

样例输入 Sample Input

aPaPBbP

3

1 2

1 3

2 3

样例输出 Sample Output

2

1

0

数据范围及提示 Data Size & Hint

1≤n≤ 105,1≤m≤ 105

很久以前就看到过的题。。大概是两年前,现在才把它写出来,想想自己这两年,有点唏嘘

如果我们对这些串建一个AC自动机,我们会发现x在y中出现的次数就是fail树里面属于y这一字符串的结点个数

然后发现输入正好每次只移动一个状态,那维护一下边移动便询问好了,按照fail边反向dfs一遍求出dfs序,用树状数组维护一下

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <string>
  6 #include <cstring>
  7 #include <cmath>
  8 #include <map>
  9 #include <stack>
 10 #include <set>
 11 #include <vector>
 12 #include <queue>
 13 #include <time.h>
 14 #define eps 1e-7
 15 #define INF 0x3f3f3f3f
 16 #define MOD 1000000007
 17 #define rep0(j,n) for(int j=0;j<n;++j)
 18 #define rep1(j,n) for(int j=1;j<=n;++j)
 19 #define pb push_back
 20 #define set0(n) memset(n,0,sizeof(n))
 21 #define ll long long
 22 #define ull unsigned long long
 23 #define iter(i,v) for(edge *i=head[v];i;i=i->next)
 24 #define max(a,b) (a>b?a:b)
 25 #define min(a,b) (a<b?a:b)
 26 #define lowbit(x) (x&-x)
 27 //#define OJ
 28 using namespace std;
 29 
 30 const int MAXINT = 100010;
 31 const int MAXNODE = 100010;
 32 const int MAXEDGE = 100010;
 33 int cnt_dfn, ans[MAXINT], m;
 34 char op[MAXINT];
 35 struct query {
 36     int x, y, id;
 37     query() {}
 38     query(int _x, int _y, int _id) :x(_x), y(_y), id(_id) {}
 39     bool operator < (const query &b) {
 40         return y < b.y;
 41     }
 42 } qr[MAXINT];
 43 struct fwt {
 44     int sum[MAXNODE], ub;
 45     void add(int p, int v) {
 46         while (p <= ub) {
 47             sum[p] += v;
 48             p += lowbit(p);
 49         }
 50     }
 51     int query(int p) {
 52         int ans = 0;
 53         while (p) {
 54             ans += sum[p];
 55             p -= lowbit(p);
 56         }
 57         return ans;
 58     }
 59 } fw;
 60 struct node {
 61     node *c[26], *fail, *pre;
 62     int dfn, max_dfn;
 63     vector<node*> eg;
 64 }*ed[MAXINT];
 65 struct ac_automaton {
 66     node mp[MAXNODE];
 67     node *q[MAXNODE];
 68     node *present, *root;
 69     int cnt;
 70     ac_automaton() {
 71         cnt = 0;
 72         present = root = new_node();
 73     }
 74     node *new_node() {
 75         return &mp[cnt++];
 76     }
 77     void back() {
 78         present = present->pre;
 79     }
 80     void add(char c) {
 81         int w = c - 'a';
 82         if (!present->c[w]) {
 83             present->c[w] = new_node();
 84             present->c[w]->pre = present;
 85         }
 86         present = present->c[w];
 87         //present->cnt++;
 88     }
 89     void get_fail() {
 90         int h = 0, t = 0;
 91         node *p, *tp;
 92         root->fail = NULL;
 93         q[t++] = root;
 94         while (h != t) {
 95             p = q[h++];
 96             rep0(i, 26) {
 97                 if (p->c[i]) {
 98                     if (p == root) p->c[i]->fail = root;
 99                     else {
100                         tp = p->fail;
101                         while (tp) {
102                             if (tp->c[i]) {
103                                 p->c[i]->fail = tp->c[i];
104                                 break;
105                             }
106                             tp = tp->fail;
107                         }
108                         if (!tp) p->c[i]->fail = root;
109                     }
110                     q[t++] = p->c[i];
111                 }
112             }
113         }
114     }
115     void link_edge() {
116         rep0(i, cnt) {
117             if (mp[i].fail) {
118                 mp[i].fail->eg.push_back(&mp[i]);
119             }
120         }
121     }
122     void dfs(node* p) {
123         p->dfn = ++cnt_dfn;
124         for (vector<node*>::iterator i = p->eg.begin(); i != p->eg.end(); ++i) {
125             dfs(*i);
126         }
127         p->max_dfn = cnt_dfn;
128     }
129 } acm;
130 int read() {
131     char c = getchar(); int f = 1, x = 0;
132     while (!isdigit(c)) { if (c == '-') f = -1; c = getchar(); }
133     while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
134     return f * x;
135 }
136 char get_ch() {
137     char c = getchar();
138     while (!isalpha(c)) c = getchar();
139     return c;
140 }
141 void get_input();
142 void work();
143 int main() {
144     freopen("in.txt", "r", stdin);
145     get_input();
146     work();
147     return 0;
148 }
149 void work() {
150     int s_cnt = 0, j = 0;
151     sort(qr, qr + m);
152     fw.ub = MAXINT;
153     int l = strlen(op);
154     rep0(i, l) {
155         if (op[i] == 'B') {
156             acm.back();
157             continue;
158         }
159         if (op[i] == 'P') {
160             s_cnt++;
161             ed[s_cnt] = acm.present;
162             continue;
163         }
164         acm.add(op[i]);
165     }
166     s_cnt = 0;
167     acm.get_fail();
168     acm.link_edge();
169     acm.dfs(acm.root);
170     acm.present = acm.root;
171     rep0(i, l) {
172         if (op[i] == 'B') {
173             fw.add(acm.present->dfn, -1);
174             acm.back();
175             continue;
176         }
177         if (op[i] == 'P') {
178             s_cnt++;
179             for (; s_cnt == qr[j].y; j++) {
180                 ans[qr[j].id] = fw.query(ed[qr[j].x]->max_dfn) - fw.query(ed[qr[j].x]->dfn - 1);
181             }
182             continue;
183         }
184         acm.add(op[i]);
185         fw.add(acm.present->dfn, 1);
186     }
187     rep0(i, m) printf("%d
", ans[i]);
188 }
189 void get_input() {
190     scanf("%s", op);
191     m = read();
192     rep0(i, m) {
193         qr[i].x = read();
194         qr[i].y = read();
195         qr[i].id = i;
196     }
197 }
许愿弥生改二
原文地址:https://www.cnblogs.com/LoveYayoi/p/6745416.html