(Next树70pts MLE*3)[NOI2011] 阿狸的打字机

一个会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 << "\n";
    }
    return 0;
}
posted @ 2021-08-26 14:42  Lecoww  阅读(27)  评论(0编辑  收藏  举报