HDU-2222 Keywords Search(AC自动机--模板题)

时间:2021-12-24 00:48:20

题目大意:统计一共出现了多少次模板串。

题目分析:AC自动机的模板题。不过这题有坑,相同的模板串不能只算一次。

代码如下:

# include<iostream>
# include<cstdio>
# include<queue>
# include<map>
# include<string>
# include<cstring>
# include<algorithm>
using namespace std; const int N=10000; int ch[N*50+5][26];
int val[N*50+5];
int last[N*50+5];
int f[N*50+5];
bool mark[N*50+5];
map<string,int>mp;
string str[N+5]; struct AC
{
int cnt,res;
void init()
{
res=cnt=0;
memset(ch,0,sizeof(ch));
memset(val,0,sizeof(val));
memset(mark,false,sizeof(mark));
}
int idx(char c)
{
return c-'a';
}
void insert(string str,int v)
{
int u=0;
int n=str.size();
for(int i=0;i<n;++i){
int c=idx(str[i]);
if(!ch[u][c]) ch[u][c]=++cnt;
u=ch[u][c];
}
val[u]=v;
}
void getFail()
{
queue<int>q;
f[0]=0;
for(int i=0;i<26;++i){
int u=ch[0][i];
if(!u) continue;
f[u]=0;
q.push(u);
last[u]=0;
}
while(!q.empty())
{
int r=q.front();
q.pop();
for(int i=0;i<26;++i){
int u=ch[r][i];
if(!u){
ch[r][i]=ch[f[r]][i];
}else{
q.push(u);
int v=f[r];
while(v&&!ch[v][i]) v=f[v];
f[u]=ch[v][i];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
}
void ac(string str)
{
int n=str.size();
int j=0;
for(int i=0;i<n;++i){
int c=idx(str[i]);
j=ch[j][c];
if(val[j]) print(j);
else if(last[j]) print(last[j]);
}
}
void print(int u)
{
if(u){
if(!mark[val[u]]) res+=mp[str[val[u]]];
mark[val[u]]=true;
print(last[u]);
}
}
int getResult()
{
return res;
}
}ac; char s[N*100+5]; int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
mp.clear();
scanf("%d",&n);
ac.init();
for(int i=1;i<=n;++i){
cin>>str[i];
++mp[str[i]];
ac.insert(str[i],i);
}
scanf("%s",s);
ac.getFail();
ac.ac(s);
printf("%d\n",ac.getResult());
}
return 0;
}