附上本章提到的Keywords Search代码~
#include
#include
#include
using namespace std;
const int MAX = 26;
struct TrieNode
{
int count;
struct TrieNode *fail; //失败指针
struct TrieNode *next【MAX】;//26个字母指针域
TrieNode()
{
count=0;
fail=NULL;
memset(next,NULL,sizeof(next));
}
};
TrieNode *q【500005】;//队列
void InsertTrie(TrieNode *pRoot,char s【】)//插入单词
{
TrieNode *p=pRoot;
if(p==NULL)
p=pRoot=new TrieNode();
int i=0;
while(s【i】)
{
int k=s【i】-'a';
if(p->next【k】==NULL)
p->next【k】=new TrieNode();
i ;
p=p->next【k】;
}
p->count ;
}
void build_ac_automation(TrieNode *pRoot)
{
int head=0,tail=0;
TrieNode *p=pRoot;
p->fail=NULL;
q【tail 】=pRoot;
while(head!=tail)
{
TrieNode *tmp=q【head 】;
for(int i=0;i < MAX;i )//设置tmp的孩子的fail指针
if(tmp->next【i】!=NULL)
{
if(tmp == pRoot)//根的孩子的fail指针指向根
tmp->next【i】->fail=pRoot;
else
{
p=tmp->fail;//递增的
while(p!=NULL)
{
if(p->next【i】!=NULL)
{
tmp->next【i】->fail=p->next【i】;
break;
}
p=p->fail;
}
if(p==NULL) tmp->next【i】->fail=pRoot;//找到,设置为根
}
q【tail 】=tmp->next【i】; //入队
}
}
}
int Search(TrieNode *pRoot,char s【】)
{
int cnt=0,k,i;
TrieNode *p,*tmp;
p=pRoot;
i=0;
while(s【i】)
{
k=s【i】-'a';
while(p->next【k】==NULL && p!=pRoot)//往p的失败指针回找,直至找到或返回根
p=p->fail;
p=p->next【k】; //一种是不通过根找到,另外或者可以通过根找到,或者为空
if(p==NULL) p=pRoot; //空,根本找不到
//可以往下找
tmp=p;
while(tmp!=pRoot && tmp->count!=-1)//以s【i】结尾的单词,通过tmp指针全部找出
{
cnt = tmp->count;
tmp->count=-1;
tmp=tmp->fail;
}
i ;
}
return cnt;
}
char str【1000005】, word【55】;
int main()
{
// freopen("a.txt","r",stdin);
int T,n,i;
cin>>T;
while(T--)
{
TrieNode *pRoot=new TrieNode();
cin>>n;
getchar();
for(i=0;i
{
gets(word);
InsertTrie(pRoot,word);
}
build_ac_automation(pRoot);
scanf("%s",str);
cout << Search(pRoot,str) << endl;
}
return 0;
}