一个会MLE的next树做法,边插入边递推fail数组(next数组,写的时候没学,自己根据ac自动机改的)
#include<bits/stdc++.h>
#define ll long long
#define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
const int maxn = 1e5 + 10;
int tr[maxn][26], cnt = 0;
int fail[maxn];
int f[maxn], d[maxn];
int now = 0;
void insert(string& s, char c)
{
int i = c - 'a';
if (!tr[now][i])
{
tr[now][i] = ++cnt;
d[cnt] = d[now] + 1;
f[cnt] = now;
now = tr[now][i];
//递推fail
int st = fail[f[now]], j = d[st] - 1;
while (st && s[j + 1] - 'a' != i)
j -= d[st], st = fail[st], j += d[st];
if (j + 1 < s.length() && s[j + 1] - 'a' == i)
fail[now] = tr[st][i];
else
fail[now] = 0;
}
else
now = tr[now][i];
}
int main()
{
fastio;
fail[0] = 0;
d[0] = 0;
cnt = 0;
memset(tr, NULL, sizeof(tr));
string p;
cin >> p;
string s = "";
int id = 0;
vector<string>mp;
mp.push_back(" ");
for (int i = 0; i < p.length(); i++)
{
char c = p[i];
if (c == 'P')
{
++id;
mp.push_back(s);
}
else if (c == 'B')
{
now = f[now];
s.pop_back();
}
else
{
insert(s,c);
s += c;
}
}
int q;
cin >> q;
while (q--)
{
int x, y;
cin >> x >> y;
string& a = mp[x];
string& b = mp[y];
//求a在b中出现多少次
int ans = 0, j = -1, now = 0;
for (int i = 0; i < b.length(); i++)
{
int to = a[j + 1] - 'a';
while (~j && a[j + 1] != b[i])
{
j -= d[now], now = fail[now], j += d[now];
to = a[j + 1] - 'a';
}
if (a[j + 1] == b[i])
{
now = tr[now][to];
j++;
if (j == a.length() - 1)
ans++, j -= d[now], now = fail[now], j += d[now];
}
}
cout << ans << "
";
}
return 0;
}