Farmer John 把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过 10510^5105 的字符串 SSS。他有一个包含 nnn 个单词的列表,列表里的 nnn 个单词记为 t1⋯tnt_1 \cdots t_nt1⋯tn。他希望从 SSS 中删除这些单词。
Farmer John 每次在 SSS 中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从 SSS 中删除这个单词。他重复这个操作直到 SSS 中没有列表里的单词为止。注意删除一个单词后可能会导致 SSS 中出现另一个列表中的单词。
Farmer John 注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在 SSS 中出现的开始位置是互不相同的。
请帮助 Farmer John 完成这些操作并输出最后的 SSS。
题意:一个字符串str,再给出多个字符串,问在str里面去掉这些字符串以后剩下的字符串。
思路:构造AC自动机,然后使用栈来实现。
对于AC自动机中的每个节点都有str中唯一字符相对应。
每找到一个字符串,我们就用在栈中减去这个字符串的长度,并且重新找
到fail树上对应的节点,继续匹配。最后输出就好了。
AC代码:
#include<bits/stdc++.h>
#include<queue>
#include<string>
#include<string.h>
#include<iostream>
#include<stdio.h>
#include<algorithm>
#define MAXN 100010
#define SIGMA_SIZE 26
#define mod 10007
#define INF 0x3f3f3f3f
#define inf 0x8f
#define SIGMA_SIZE 26
#define low(x) (x&(-x))
using namespace std;
typedef long long LL;
int trie[MAXN][SIGMA_SIZE],val[MAXN];
int f[MAXN],last[MAXN],sum[MAXN];
int tot,n,m;
char str[MAXN],stg[MAXN];
int p[MAXN];int cnt,snt;
char q[MAXN];
void init()
{
tot=1;cnt=0;snt=0;
memset(trie,0,sizeof(trie));
memset(val,0,sizeof(val));
memset(f,0,sizeof(f));
memset(last,0,sizeof(last));
memset(sum,0,sizeof(sum));
}
void cal(int root)
{
if(root)
{
sum[val[root]]++;
cal(last[root]);
}
}
void Insert(char *str,int v)
{
int root=0;
int len=strlen(str);
for(int i=0;i<len;i++)
{
int id=str[i]-'a';
int v=trie[root][id];
if(!v)
{
memset(trie[tot],0,sizeof(trie[tot]));
val[tot]=0;
trie[root][id]=tot++;
}
root=trie[root][id];
}
val[root]=v;
}
void getfail()
{
queue<int> q;f[0]=0;
for(int c=0;c<SIGMA_SIZE;c++)
{
int u=trie[0][c];
if(u)
{
q.push(u);f[u]=0;last[u]=0;
}
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int c=0;c<SIGMA_SIZE;c++)
{
int u=trie[r][c];
if(!u)
{
trie[r][c]=trie[f[r]][c];
continue;
}
int v=f[r];q.push(u);
f[u]=trie[v][c];last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
void query(char *str)
{
int root=0;int len=strlen(str);
for(int i=0;i<len;i++)
{
int id=str[i]-'a';
while(root&&!trie[root][id])
root=trie[root][id];
root=trie[root][id];
p[cnt++]=root;
q[snt++]=str[i];
if(val[root])
{
cnt-=val[root];
snt-=val[root];
root=p[cnt-1];
}
}
q[snt]='\0';
}
int main()
{
scanf("%s",stg);
scanf("%d",&n);
init();
for(int i=0;i<n;i++)
{
scanf("%s",str);
Insert(str,strlen(str));
}
getfail();
query(stg);
printf("%s",q);
return 0;
}