3 aaa bbb ccc 2 aaabbbccc bbaacc
web 1: 1 2 3 total: 1
此题是典型的多模式串匹配问题,ac自动机即可解决。我的ac自动机代码是套用的网上大牛的模板,然后自己结合题目做了一下修改,题目在几次RE之后终于AC了。总的时间复杂度为O(n*len(s)).
#include <iostream> #include<algorithm> using namespace std; const int kind = 128; struct node { node *fail; //失败指针 node *next[kind]; //Tire每个节点的26个子节点(最多26个字母) int count; //是否为该单词的最后一个节点 node() { //构造函数初始化 fail=NULL; count=0; memset(next,NULL,sizeof(next)); } }*q[500*200+1000]; //队列,方便用于bfs构造失败指针,大小应依据Tries图节点个数而定 char keyword[200+20]; //输入的单词 char str[10000+10]; //模式串 int INdex[1000+10][5]; int num[1000+10]; int head,tail; //队列的头尾指针 void insert(char *str,node *root,int ind) //建立一颗以root为根节点的不带前缀指针的字典树 { node *p=root; int i=0,index; while(str[i]) { index=str[i]; if(p->next[index]==NULL) p->next[index]=new node(); p=p->next[index]; i++; } p->count=ind; } void build_ac_automation(node *root) //在建好的字典树上添加前缀指针,形成Tries图,即ac自动机 { int i; root->fail=NULL; q[head++]=root; while(head!=tail) { node *temp=q[tail++]; node *p=NULL; for(i=0;i<128;i++) { if(temp->next[i]!=NULL) { if(temp==root) temp->next[i]->fail=root; 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=root; } q[head++]=temp->next[i]; } } } } int query(node *root,int ind) //有多少种模式串出现在母串str[]中 { int i=0,cnt=0,index,len=strlen(str),j; node *p=root; while(str[i]) { index=str[i]; while(p->next[index]==NULL && p!=root) p=p->fail; p=p->next[index]; p=(p==NULL)?root:p; node *temp=p; while(temp!=root&&temp->count) { for(j=0;j<num[ind];j++) if(INdex[ind][j]==temp->count) break; if(j>=num[ind]) INdex[ind][num[ind]++]=temp->count; temp=temp->fail; } i++; } return cnt; } int main() { int n,t,i,m,j,tag; while(~scanf("%d",&n)) { head=tail=0; node *root=new node(); getchar(); for(i=1;i<=n;i++) { gets(keyword); insert(keyword,root,i); } build_ac_automation(root); scanf("%d",&m); getchar(); memset(INdex,0,sizeof(INdex)); memset(num,0,sizeof(num)); for(i=1;i<=m;i++) { gets(str); query(root,i); } tag=0; for(i=1;i<=m;i++) { if(num[i]) { tag++; printf("web %d:",i); sort(INdex[i],INdex[i]+num[i]); for(j=0;j<num[i]-1;j++) printf(" %d",INdex[i][j]); printf(" %d\n",INdex[i][j]); } } printf("total: %d\n",tag); } return 0; }