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;
}