题意:给n个字符串 和m个字符串对 问对于每个字符串对 他最多是n里面多少个字符串的前缀和后缀
一道比较基础的AC自动机的题目 简单点说就是重新构造字符串和需要匹配的字符串对
以样例为例:
aaaaa 就改造为aaaaa}aaaaa 中间那个是26个字母之后的一个字符
而字符串对于a aa为例就改造为aa}a
可以看到假设字符串分别是字符串的前缀和后缀的话那么在两者的“}”两边必然是可以匹配的 那么
问题就转化为对于n个字符串和m个字符串 判断n中每个字符串最多包含多少个m中的字符串 这恰好
就是AC自动机的模型。
感谢一位师兄的shared code 代码思路很清晰 非常有帮助
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define maxn 222222
vector<int>v;
char a[maxn],pre[maxn],suf[maxn],buf[maxn];
int ans[maxn],num[maxn];
int n,m,be[maxn];
struct ato
{
int fail[maxn],end[maxn],val[maxn];
int next[maxn][28];
int root,L;
int newnode()
{
for(int i=0;i<27;i++) next[L][i]=-1;
end[L++]=0;
return L-1;
}
void ini()
{
L=0;
root=newnode();
}
void insert(int id)
{
int len=strlen(buf);
int now=root;
for(int i=0;i<len;i++)
{
if(next[now][buf[i]-'a']==-1)
{
next[now][buf[i]-'a']=newnode();
}
now=next[now][buf[i]-'a'];
}
ans[id]=now;
end[now]++;
}
void build()
{
queue<int>q;
fail[root]=root;
for(int i=0;i<27;i++)
{
if(next[root][i]==-1)
{
next[root][i]=root;
}
else
{
fail[next[root][i]]=root;
q.push(next[root][i]);
}
}
while(!q.empty())
{
int now=q.front();
v.push_back(now);
q.pop();
for(int i=0;i<27;i++)
{
if(next[now][i]==-1)
{
next[now][i]=next[fail[now]][i];
}
else
{
fail[next[now][i]]=next[fail[now]][i];
q.push(next[now][i]);
}
}
}
}
void query()
{
int len=strlen(buf);
int now=root;
for(int i=0;i<len;i++)
{
now=next[now][buf[i]-'a'];
num[now]++;
}
}
void work()
{
int len=v.size()-1;
for(int i=len;i>=0;i--)
{
num[fail[v[i]]]+=num[v[i]];
}
}
}ac;
int main()
{
ac.ini();
scanf("%d",&n);
int now=0;
for(int i=1;i<=n;i++)
{
be[i]=now;
scanf("%s",a+now);
while(a[now]) now++;
}
be[n+1]=now;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s%s",pre,suf);
int len=strlen(suf);
int len1=strlen(pre);
int cnt=0;
for(int j=0;j<len;j++)
{
buf[cnt++]=suf[j];
}
buf[cnt++]='z'+1;
for(int j=0;j<len1;j++)
{
buf[cnt++]=pre[j];
}
buf[cnt]='\0';
ac.insert(i);
}
ac.build();
for(int i=1;i<=n;i++)
{
int cnt=0;
for(int j=be[i];j<be[i+1];j++)
{
buf[cnt++]=a[j];
}
buf[cnt++]='z'+1;
for(int j=be[i];j<be[i+1];j++)
{
buf[cnt++]=a[j];
}
buf[cnt]='\0';
//cout<<buf<<endl;
ac.query();
}
ac.work();
for(int i=1;i<=m;i++) printf("%d\n",num[ans[i]]);
}
/*
1
abcdefcd
3
ab cd
a cd
ad cd
0
0
0
3
ascblkjklj
dklfjdklfj
sldjfkl
5
asc lj
a j
dk jdklfj
dk jj
sss lll
0
1
1
0
0
*/