bzoj 2434 AC自动机 + fail指针建树 + 树状数组
思路:我们先跟着它给定的字符串走把字典树建出来,求出fail指针,我们考虑两个字符串 A和B,
如果想要求B中有多少A的子串,转换一下就是有多少个B的前缀的后缀包含A,这个在AC自动机
的状态图中很容易表示,就是字符串B所占的结点中 有多少个结点顺着fail能到达A的尾结点,
并且fail构建出来的图是一棵树,转换成A的尾结点的子树中有多少个B的节点,用dfs序构建树状
数组能很容易完成,又因为有m组询问,我们把询问离线排序,就能解决问题啦。
#include<bits/stdc++.h> #define LL long long #define ll long long #define fi first #define se second #define mk make_pair #define PII pair<int, int> #define y1 skldjfskldjg #define y2 skldfjsklejg using namespace std; const int N = 2e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1000000007; int n, m, pos, ans[N], t[N]; char s[N]; struct Qus { int x, y, id; bool operator < (const Qus &rhs) const { return y < rhs.y; } } qus[N]; struct BIT { int a[N]; void modify(int x, int v) { for(int i = x; i < N; i += i & -i) a[i] += v; } int sum(int x) { int ans = 0; for(int i = x; i; i -= i & -i) ans += a[i]; return ans; } } bit; struct Ac { int ch[N][26], val[N], dp[N], f[N], L[N], R[N], tot, sz, cnt, all; bool vis[N]; vector<PII> vec[N]; vector<int> edge[N]; Ac(int sz) {this->sz = sz;} void init() {tot = 0;} int newNode() { tot++; f[tot] = 0; val[tot] = 0; memset(ch[tot], 0, sizeof(ch[tot])); return tot; } inline int idx(char c) {return c - 'a';} void addStr(char *s) { stack<int> stk; int u = 0; stk.push(0); for(int i = 0; s[i]; i++) { if(s[i] == 'P') { cnt++; val[u]++; t[cnt] = u; while(pos <= n && qus[pos].y <= cnt) vec[u].push_back(mk(qus[pos].x, qus[pos].id)), pos++; } else if(s[i] == 'B') { if(stk.size() > 1) { stk.pop(); u = stk.top(); } } else { int c = idx(s[i]); if(!ch[u][c]) ch[u][c] = newNode(); u = ch[u][c]; stk.push(u); } } } void build() { queue<int> que; for(int c = 0; c < sz; c++) { int v = ch[0][c]; if(!v) ch[0][c] = 0; else f[v] = 0, que.push(v); } while(!que.empty()) { int u = que.front(); que.pop(); val[u] |= val[f[u]]; for(int c = 0; c < sz; c++) { int v = ch[u][c]; if(!v) ch[u][c] = ch[f[u]][c]; else f[v] = ch[f[u]][c], que.push(v); } } } void dfs(int u) { L[u] = ++all; for(int i = 0; i < edge[u].size(); i++) { int v = edge[u][i]; dfs(v); } R[u] = all; } void solve(char *s) { for(int i = 1; i <= tot; i++) edge[f[i]].push_back(i); dfs(0); stack<int> stk; int u = 0; stk.push(0); bit.modify(L[0], 1); for(int i = 0; s[i]; i++) { if(s[i] == 'P') { if(vis[u]) continue; vis[u] = true; for(int i = 0; i < vec[u].size(); i++) { int x = t[vec[u][i].fi], id = vec[u][i].se; ans[id] = bit.sum(R[x]) - bit.sum(L[x] - 1); } } else if(s[i] == 'B') { if(stk.size() > 1) { bit.modify(L[u], -1); stk.pop(); u = stk.top(); } } else { int c = idx(s[i]); u = ch[u][c]; stk.push(u); bit.modify(L[u], 1); } } for(int i = 1; i <= n; i++) printf("%d\n", ans[i]); } } ac(26); int main() { ac.init(); pos = 1; scanf("%s%d", s, &n); for(int i = 1; i <= n; i++) { scanf("%d%d", &qus[i].x, &qus[i].y); qus[i].id = i; } sort(qus + 1, qus + 1 + n); ac.addStr(s); ac.build(); ac.solve(s); return 0; } /* */