题意:预先给你一些单词,然后给你一个字符串,在判断有多少个单词出现在这个字符串中。
分析:使用AC自动机解决。下面是自己写的类模版。可以直接使用。最后记得释放内存。
#include<iostream> #include<queue> using namespace std; #define LETTER_COUNT 26 class AC_Automation { private: struct Node { Node* fail; //失败指针 Node* next[LETTER_COUNT]; //Tire树节点的子节点 int count; //是否为该单词的最后一个节点 Node() { fail=NULL; count=0; memset(next,NULL,sizeof(next)); } }; Node* m_sroot; void Delete(Node* p); public: AC_Automation(){ m_sroot=(Node*)new Node();} ~AC_Automation(){ Delete(m_sroot);} void AddWord(char* str); //添加一个单词 void Build_AC_Automation(); int GetMatchingCount(char* str); }; int AC_Automation::GetMatchingCount(char* str) { int cnt=0,index; Node* p,*temp; p=m_sroot; while(*str) { index=*str-'a'; while(p->next[index]==NULL && p!=m_sroot) p=p->fail; p=p->next[index]; p=(p==NULL)?m_sroot:p; temp=p; while(temp!=m_sroot && temp->count!=-1) //确保当前字符前面包含的所有单词都被匹配 { cnt+=temp->count; temp->count=-1; temp=temp->fail; } str++; } return cnt; } void AC_Automation::Delete(Node* p) { for(int i=0;i<LETTER_COUNT;i++) if(p->next[i]!=NULL) Delete(p->next[i]); delete p; } void AC_Automation::Build_AC_Automation() { int i; Node *temp,*p; queue<Node*> q; //队列,用于BFS,建立失败指针 m_sroot->fail=NULL; q.push(m_sroot); while(!q.empty()) { temp=q.front(); q.pop(); p=NULL; for(i=0;i<LETTER_COUNT;i++) { if(temp->next[i]!=NULL) { if(temp==m_sroot) temp->next[i]->fail=m_sroot; else { p=temp->fail; while(p!=NULL) { if(p->next[i]!=NULL) { temp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) temp->next[i]->fail=m_sroot; } q.push(temp->next[i]); //子节点如队列 } } } } void AC_Automation::AddWord(char* str) { Node* p=m_sroot; int i=0; int index; while(*str) { index=*str-'a'; if(p->next[index]==NULL) p->next[index]=(Node*)new Node(); p=p->next[index]; str++; } p->count++; //单词的最后一个节点加1,单表新加入一个单词 } int main() { int T,N,i; char a[51]; char b[1000001]; cin>>T; while(T--) { AC_Automation ac_auto; cin>>N; for(i=0;i<N;i++) { cin>>a; ac_auto.AddWord(a); } ac_auto.Build_AC_Automation(); cin>>b; cout<<ac_auto.GetMatchingCount(b)<<endl; } return 0; }
时间: 2024-11-10 17:10:04