第一道AC自动机留念,HDU第500题留念。
学习了Just Me牛的代码风格。
#include <cstdio>
#include <queue>
#include <cstdlib>
using namespace std;
const int maxn=1e6+5;
char s[maxn];
struct Trie
{
int count;
Trie *fail, *next[26];
Trie()
{
count=0;
for(int i=0 ; i<26 ; i++ )
next[i] = NULL;
fail = NULL;
}
};
Trie *root;
void insert(char *s)
{
Trie *p = root;
for(int i = 0 ; s[i] ; i++)
{
int id = s[i]-'a';
if(p -> next[id] == NULL)
p -> next[id]= new Trie();
p = p -> next[id];
}
p->count++;
}
void Build_AC()
{
queue<Trie *>q;
q.push(root);
while(!q.empty())
{
Trie *p = q.front();
q.pop();
for(int i = 0; i < 26 ;i++)
if(p -> next[i] != NULL){
if(p == root)
p ->next[i] ->fail = root;
else
{
Trie *temp = p ->fail;
while(temp != NULL)
{
if(temp -> next[i] != NULL){
p ->next[i] ->fail = temp ->next[i];
break;
}
temp=temp ->fail;
}
if(temp == NULL) p ->next[i] ->fail = root;
}
q.push(p ->next[i]);
}
}
}
int AC(char *s)
{
Build_AC();
Trie *p=root;
int ret=0,index;
for(int i = 0; s[i] ; i++ ){
index = s[i]-'a';
while(p != root && p -> next[index] == NULL)
p = p -> fail;
p = p -> next[index];
if( p == NULL)
{
p = root;
continue;
}
Trie *temp=p;
while(temp != root && temp -> count != 0)
{
ret += temp -> count;
temp -> count = 0 ;
temp = temp -> fail;
}
}
return ret;
}
void deal(Trie *T)
{
for(int i = 0 ; i<26 ; i++)
if(T->next[i] != NULL)
deal(T->next[i]);
free(T);
}
int main()
{
int T,n;
scanf("%d", &T);
while( T-- )
{
scanf("%d",&n);
root=new Trie();
getchar();
while(n--){
scanf("%s",s);
insert(s);
}
scanf("%s",s);
printf("%d\n",AC(s));
deal(root);
}
return 0;
}