题目描述
题解
和BZOJ3942是差不多的。
搞一个栈,然后边匹配边压栈,匹配不了就跳到失配,匹配成功就暴力弹栈。
需要注意的一点是,弹栈之后要将当前匹配的节点恢复到栈顶元素的位置,然后从下一个元素开始继续匹配。
单个串kmp就可以完成,多个串改成AC自动机来做。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define N 100005
char s[N],t[N];
int n,sz,len,top,lt[N],ch[N][30],fail[N],is_end[N],stack[N],loc[N];
queue <int> q;
void insert(int id)
{
int len=strlen(t),now=0;
for (int i=0;i<len;++i)
{
int x=t[i]-'a';
if (!ch[now][x]) ch[now][x]=++sz;
now=ch[now][x];
}
is_end[now]=id;
}
void make_fail()
{
while (!q.empty()) q.pop();
for (int i=0;i<26;++i)
if (ch[0][i]) q.push(ch[0][i]);
while (!q.empty())
{
int now=q.front();q.pop();
for (int i=0;i<26;++i)
{
if (!ch[now][i])
{
ch[now][i]=ch[fail[now]][i];
continue;
}
fail[ch[now][i]]=ch[fail[now]][i];
q.push(ch[now][i]);
}
}
}
void ac()
{
int now=0;
for (int i=0;i<len;++i)
{
stack[++top]=i;
int x=s[i]-'a';
int y=ch[now][x];
if (y&&is_end[y])
{
int tmp=lt[is_end[y]];
top-=tmp;
now=loc[stack[top]];
continue;
}
loc[i]=now=y;
}
}
int main()
{
gets(s);len=strlen(s);
scanf("%d\n",&n);
for (int i=1;i<=n;++i)
{
gets(t);lt[i]=strlen(t);
insert(i);
}
make_fail();
ac();
for (int i=1;i<=top;++i)
putchar(s[stack[i]]);
putchar('\n');
}