P3121 Censoring G

P3121 Censoring G

题意:

给出一个字符串,给出一堆子串,每次删除左边第一个子串,输出最终通过删除没有子串的字符串。

思路:

因为是一对多,所以可以很自然的想到利用AC自动机。+栈,注意因为删除之后,当前到达的位置是现在栈顶所在的位置,所以还需要存储每个元素指到哪里。

实现:

#include <stdio.h>
#include <cstring>
#include <stack>
#include <algorithm>
using namespace std;
const int N = 1e6 + 5;
int tr[N][26], idx = 1, cnt[N], nex[N], q[N];
char s[N], str[N];
struct node
{
    char a;
    int b;
};
stack<node> stk;
void insert()
{
    int p = 0;
    for (int i = 1; s[i]; i++)
    {
        int to = s[i] - 'a';
        if (!tr[p][to])
            tr[p][to] = idx++;
        p = tr[p][to];
    }
    cnt[p] = strlen(s + 1);
}
void build()
{
    int hh = 1, tt = 0;
    for (int i = 0; i < 26; i++)
        if (tr[0][i])
            q[++tt] = tr[0][i];
    while (hh <= tt)
    {
        int t = q[hh++];
        for (int i = 0; i < 26; i++)
        {
            int &p = tr[t][i];
            if (!p)
                p = tr[nex[t]][i];
            else
            {
                nex[p] = tr[nex[t]][i];
                q[++tt] = p;
            }
        }
    }
}
int main()
{
    scanf("%s", str + 1);
    int n;
    scanf("%d", &n);
    while (n--)
    {
        scanf("%s", s + 1);
        insert();
    }
    build();
    int len = strlen(str + 1);
    for (int i = 1, j = 0; i <= len; i++)
    {
        int t = str[i] - 'a';
        j = tr[j][t];
        stk.push({str[i], j});
        if (cnt[j])
        {
            int tem = cnt[j];
            while (tem && !stk.empty())
            {
                stk.pop();
                tem--;
            }
            if (!stk.empty())
                j = stk.top().b;
            else
                j = 0;
        }
    }
    int st = 1;
    while (!stk.empty())
    {
        str[st++] = stk.top().a;
        stk.pop();
    }
    for (int i = st - 1; i >= 1; i--)
        printf("%c", str[i]);
    return 0;
}
posted @ 2022-08-07 17:59  zxr000  阅读(38)  评论(0编辑  收藏  举报