题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222
题目大意:给n个模板串,求长串中模板串的个数;
解题思路:
自动机入门题,注意模板重复串。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#define INF 0x7fffffff
#define SUP 0x80000000
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
const int N=100007;
/******************auther:ACsorry******************/
struct Trie{
Trie *next[26];
Trie *fail;
int flag;
Trie(){
mem(next,0);
fail=0;
flag=0;
}
};
int tot;
Trie *p[500007];
Trie* newTrie()
{
p[tot]=new Trie();
tot++;
return p[tot-1];
}
void sInsert(Trie *root,char *s)
{
int i=0;
Trie *p=root;
while(s[i]){
int idx=s[i]-'a';
if(p->next[idx]==NULL){
p->next[idx]=newTrie();
}
p=p->next[idx];
i++;
}
p->flag++;
}
void buildAc(Trie *root)
{
queue<Trie*> que;
que.push(root);
while(!que.empty()){
Trie *cur=que.front();
que.pop();
for(int i=0;i<26;i++){
if(cur->next[i]){
if(cur==root) cur->next[i]->fail=root; //第一个元素匹配
else{
Trie *p=cur->fail;
while(p){ //搜索匹配
if(p->next[i]){
cur->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL) cur->next[i]->fail=root; //匹配为空,从头开始
}
que.push(cur->next[i]);
}
}
}
}
int solve(Trie *root,char *s)
{
int ret=0;
int len=strlen(s);
Trie *p=root;
for(int i=0;i<len;i++){
int idx=s[i]-'a';
while(p->next[idx]==NULL&&p!=root) p=p->fail;
p=p->next[idx];
if(p==NULL) p=root;
Trie *tmp=p; //ret+=(以p为后缀的串)
while(tmp!=root&&tmp->flag!=-1){
ret+=tmp->flag;
tmp->flag=-1;
tmp=tmp->fail;
}
}
return ret;
}
char s[1000007];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
Trie *root=newTrie();
for(int i=0;i<n;i++)
{
scanf("%s",s);
sInsert(root,s);
}
buildAc(root);
scanf("%s",s);
printf("%d\n",solve(root,s));
for(int i=0;i<tot;i++) delete p[i];
}
return 0;
}