3942题解:
定义f[i] 为S串以第i位结尾的后缀,最长可以是T串多长的前缀,这一个可以用KMP匹配。
可以用一个first数组记录i字符前一个未被匹配的位置是哪一个,当f[i]=len(T)时,就可以将最末尾的len(T)个字符匹配了。
3940只需要把KMP换为AC自动机就可以。
3942:
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 1000005
using namespace std;
char s1[maxn];
char s2[maxn];
int fail[maxn];
void get_kmp()
{
fail[1]=0;
int n=strlen(s2+1);
for(int i=2;i<=n;i++)
{
int p=fail[i-1];
while(p&&s2[p+1]!=s2[i]) p=fail[p];
if(s2[p+1]==s2[i]) fail[i]=p+1;
}
}
int fst[maxn];
int cp[maxn];
bool use[maxn];
int find(int x)
{
if(use[fst[x]])
fst[x]=find(fst[x]);
return fst[x];
}
void work()
{
int l1=strlen(s1+1);
int l2=strlen(s2+1);
for(int i=1;i<=l1;i++)
fst[i]=i-1;
for(int i=1;i<=l1;i++)
{
int p=cp[find(i)];
while(p&&s2[p+1]!=s1[i]) p=fail[p];
if(s2[p+1]==s1[i]) cp[i]=p+1;
if(cp[i]==l2)
{
int x=i;
for(int j=1;j<=l2;j++)
use[x]=1,x=find(x);
}
}
}
int main()
{
scanf("%s",s1+1);
scanf("%s",s2+1);
get_kmp();work();
int l=strlen(s1+1);
for(int i=1;i<=l;i++)
if(!use[i]) putchar(s1[i]);
return 0;
}
3940:
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 100005
using namespace std;
char s[maxn];
char s1[maxn];
bool use[maxn];
int fst[maxn],cp[maxn];
int find(int x)
{
if(use[fst[x]])
fst[x]=find(fst[x]);
return fst[x];
}
struct Trie
{
int val[maxn];
int fail[maxn];
int deep[maxn];
int ch[maxn][27],cnt;
void insert()
{
int p=0;
int n=strlen(s+1);
for(int i=1;i<=n;i++)
{
int c=s[i]-'a'+1;
if(!ch[p][c]) ch[p][c]=++cnt;
p=ch[p][c];deep[p]=i;
}
val[p]++;
}
queue<int> Q;
void build()
{
for(int i=1;i<=26;i++)
if(ch[0][i]) Q.push(ch[0][i]);
while(!Q.empty())
{
int r=Q.front();Q.pop();
for(int i=1;i<=26;i++)
{
int u=ch[r][i];
if(!u)
{
ch[r][i]=ch[fail[r]][i];
continue;
}
Q.push(u);
int p=fail[r];
while(p&&!ch[p][i]) p=fail[p];
fail[u]=ch[p][i];
}
}
}
void work()
{
int l=strlen(s1+1);
for(int i=1;i<=l;i++)
fst[i]=i-1;
for(int i=1;i<=l;i++)
{
int p=cp[find(i)];
int c=s1[i]-'a'+1;
while(p&&!ch[p][c]) p=fail[p];
if(ch[p][c]) p=ch[p][c];
cp[i]=p;
if(val[p])
{
int x=i;
for(int j=1;j<=deep[p];j++)
use[x]=1,x=find(x);
}
}
}
}AC;
int main()
{
scanf("%s",s1+1);
int n;scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
AC.insert();
}
AC.build();
AC.work();
int l=strlen(s1+1);
for(int i=1;i<=l;i++)
if(!use[i]) putchar(s1[i]);
return 0;
}