阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机 上只有 28 个按键,分别印有 26 个小写英文字母和'B'、'P'两个字母。 经阿狸研究发现,这个打字机是这样工作的:
输入小写字母,打字机的一个凹槽中会加入这个字母(按 P 前凹槽中至 少有一个字母)。
按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。
按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并 换行,但凹槽中的字母不会消失(保证凹槽中至少有一个字母)。
例如,阿狸输入 aPaPBbP,纸上被打印的字符如下: a aa ab 我们把纸上打印出来的字符串从 1 开始顺序编号,一直到 n。打字机有一个 非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数 (x,y)(其中 1≤x,y≤n),打字机会显示第 x 个打印的字符串在第 y 个打印的字符串 中出现了多少次。 阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助 他么?
输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。 第二行包含一个整数 m,表示询问个数。 接下来 m 行描述所有由小键盘输入的询问。其中第 i 行包含两个整数 x, y, 表示第 i 个询问为(x, y)。
输出 m 行,其中第 i 行包含一个整数,表示第 i 个询问的答案。
aPaPBbP
3
1 2
1 3
2 3
2
1
0
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 }