题目
化简题目:多个匹配串,多个文本串,求文本串恰好被匹配串拼接的最长前缀
做法
显然我们对文本串建AC自动机,然后标记末节点
建(tire)图,需要注意的是:末节点标记不能下传,原因在于对文本串跑差分的操作,自己想想吧
多于每个文本串跑(trie)图,对每个字符到达一个点后沿着(fail)往上跑,如果是末节点,说明我们匹配到一个串了,然后做差分就好了
My complete code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef int LL;
const LL maxn=1e6;
LL nod=1;
LL son[maxn][26],fail[maxn],dep[maxn];
bool falg[maxn];
inline void Insert(char *s){
LL Len=strlen(s+1),now=0;
for(LL i=1;i<=Len;++i){
LL c=s[i]-'a';
if(son[now][c]==0){
son[now][c]=++nod;
//dep[nod]=dep[now]+1;
}
now=son[now][c];
dep[now]=i;
}falg[now]=true;
}
LL n,T;
LL cf[maxn];
bool visit[maxn];
char s[maxn];
inline void F_fail(){
queue<LL>que;
for(LL i=0;i<26;++i)
if(son[0][i])
que.push(son[0][i]);
while(que.size()){
LL u(que.front()); que.pop();
for(LL i=0;i<26;++i){
LL v(son[u][i]);
if(v){
fail[v]=son[fail[u]][i],
que.push(v);
}else
son[u][i]=son[fail[u]][i];
}
}
}
int main(){
scanf("%d%d",&n,&T);
for(LL i=1;i<=n;++i){
scanf(" %s",s+1);
Insert(s);
}
F_fail();
while(T--){
scanf(" %s",s+1);
LL now(0),Len=strlen(s+1);
memset(visit,false,sizeof(visit));memset(cf,0,sizeof(cf));
visit[0]=true;
for(LL i=1;i<=Len;++i){
LL c=s[i]-'a';
now=son[now][c];
for(LL u=now;u;u=fail[u])
if(falg[u]&&visit[i-dep[u]]){
visit[i]=true,
++cf[i-dep[u]+1],
--cf[i+1];
}
}now=0; LL ans(0);
for(LL i=1;i<=Len;++i){
now+=cf[i];
if(now==0)
break;
else
++ans;
}
printf("%d
",ans);
}
}/*
*/