题意是给了很多单词,然后给一个字符串,问字符串里包含了几个给定的单词
例如she he say shr her 问yasherhs含了几个,三个,注意she和he分别为两个单词,如果遍历一遍字符串显然是不够的,这时候用AC自动机就不会超时了
注意可能要有重复的单词
还有flag还是必须的
#include <iostream>
#include <string.h>
#include <iostream>
#include <queue>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
char str[1000005];
typedef struct node
{
struct node *next[26],*fail;
int num,flag;
}TrieNode,*trie;
TrieNode* creatTrie()
{
TrieNode* node=(TrieNode*)malloc(sizeof(TrieNode));
for(int i=0; i<26; i++)
node->next[i]=NULL;
node->fail=NULL;
node->num=0;
node->flag=0;
return node;
}
void trieInsert(trie root)
{
trie p=root;
char *s=str;
int id;
while(*s)
{
//printf("%c ",*s);
id=*s-'a';
if(p->next[id]==NULL)
p->next[id]=creatTrie();
p=p->next[id];
++s;
}
p->num++;
}
void getfail(trie root)
{
trie p=root,now,son;
queue<trie>q;
q.push(p);
while(!q.empty())
{
now=q.front();
q.pop();
for(int i=0;i<26;i++)
{
son=now->next[i];
if(son!=NULL)
{
if(now==root)
son->fail=root;
else
{
p=now->fail;
while(p)
{
if(p->next[i])
{
son->fail=p->next[i];
break;
}
p=p->fail;
}
if(!p)//
son->fail=root;
}
q.push(son);
}
}
}
}
int find(trie root)
{
trie p=root,temp;
//ar *p=str;
int t=0;
int len=strlen(str);
for(int i=0;i<len;i++)
{
int pos=str[i]-'a';
while(!p->next[pos]&&p!=root)
{
p=p->fail;
}
p=p->next[pos];
if(!p)
p=root;
temp=p;
while(temp!=root&&temp->flag!=1)
{
t+=temp->num;
temp->flag=1;
temp=temp->fail;
}
}
return t;
}
int main()
{
int test,n;
scanf("%d",&test);
while(test--)
{
trie root=creatTrie();
scanf("%d",&n);
while(n--)
{
scanf("%s",str);
trieInsert(root);
}
getfail(root);
scanf("%s",str);
printf("%d\n",find(root));
}
return 0;
}
/*
2
5
she
se
say
shr
her
yasherhs
*/