一、题目
二、解法
本题最重要的条件是:列表中的单词不会出现一个单词是另一个单词子串的情况
,所以下图的情况是不可能出现的(大包含小,却删掉了小)。
所以就是
自动机板题了,用栈维护一下就行了,时间复杂度
。
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int M = 100005;
int read()
{
int x=0,flag=1;
char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,top,h[M],w[M];
char s[M],t[M];
struct Automaton
{
int c[M][26],val[M],fail[M],cnt;
void ins(char *s)
{
int len=strlen(s),now=0;
for(int i=0; i<len; i++)
{
int v=s[i]-'a';
if(!c[now][v]) c[now][v]=++cnt;
now=c[now][v];
}
val[now]=len;
}
void build()
{
queue<int> q;
for(int i=0; i<26; i++) if(c[0][i]) q.push(c[0][i]);
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=0; i<26; i++)
if(c[t][i]) fail[c[t][i]]=c[fail[t]][i],q.push(c[t][i]);
else c[t][i]=c[fail[t]][i];
}
}
void solve()
{
m=strlen(s);
for(int i=0,now=0; i<m; i++)
{
int v=s[i]-'a';
now=c[now][v];
h[++top]=i;
w[top]=now;
if(val[now])
{
top-=val[now];
now=w[top];
}
}
for(int i=1; i<=top; i++)
printf("%c",s[h[i]]);
puts("");
}
} AC;
int main()
{
scanf("%s",s);
n=read();
for(int i=1; i<=n; i++)
{
scanf("%s",t);
AC.ins(t);
}
AC.build();
AC.solve();
}