HDU 2222 Keywords Search (AC自动机)

 

题意:给一堆关键字(单词),再给一串,求此串中出现几次关键字。(多模式串匹配)

思路:以关键字建立trie树,设置好fail指针,就可以进行求出现次数了。 

 

内存超了!!!开数组也超,开链表都超。。。我去

  1 #include<bits/stdc++.h>

  2 using namespace std;

  3 const int N=1000000+100;

  4 char tar[N];

  5 int len, p, q;

  6 string str;

  7 struct node

  8 {

  9     int flag;  //终止标志

 10     node* s[26];   //指向孩子的指针

 11     node* fail;

 12 }a[500001];

 13 

 14 deque<node*> que;

 15 node *create()

 16 {

 17     node* tmp=&a[q++];

 18     //node* tmp=new(node);

 19     for(int i=0; i<26; i++)    tmp->s[i]=0;

 20     tmp->flag=0;

 21     tmp->fail=0;

 22     return tmp;

 23 }

 24 

 25 void input(int p, node *t)

 26 {

 27     if(!t->s[str[p]-'a'])    t->s[str[p]-'a']=create();

 28     node* tmp=t->s[str[p]-'a'];

 29     if(++p>=len)  //结束

 30     {

 31         tmp->flag++;

 32         return;

 33     }

 34     input(p, tmp);

 35 }

 36 

 37 void BFS(node* t)

 38 {

 39     que.clear();

 40     for(int i=0; i<26; i++)  //先处理第2层的

 41         if(t->s[i])

 42         {

 43             que.push_back(t->s[i]);

 44             t->s[i]->fail=t;

 45         }

 46 

 47     while(!que.empty())

 48     {

 49         int siz=que.size();

 50         while(siz--)    //处理一层

 51         {

 52             node *tmp=que.front();

 53             que.pop_front();

 54             for(int i=0; i<26; i++)  //处理此结点的每个孩子

 55             {

 56                 if(tmp->s[i])

 57                 {

 58                     que.push_back(tmp->s[i]);

 59                     node *k=tmp->fail;  //k和当前结点相同

 60                     while( k!=t && !k->s[i] )

 61                         k=k->fail;

 62 

 63                     if(k==t && !k->s[i])    tmp->s[i]->fail=t;

 64                     else    tmp->s[i]->fail=k->s[i];

 65                 }

 66             }

 67 

 68         }

 69     }

 70 }

 71 

 72 int search(int p, node* t)

 73 {

 74     len=strlen(tar);

 75     node *temp=t;

 76     int cnt=0;

 77     while(p<len)

 78     {

 79         if(temp->flag) //判断是否为匹配

 80         {

 81             cnt+=temp->flag;

 82             temp->flag=0;

 83         }

 84         if(tar[p]<'a'||tar[p]>'z')  //非法字符

 85         {

 86             temp=t;

 87             continue;

 88         }

 89         if(temp->s[tar[p]-'a']) //继续往下匹配

 90         {

 91             temp=temp->s[tar[p]-'a'];

 92             p++;

 93         }

 94         else

 95         {

 96             if(temp==t)    p++;

 97             else    temp=temp->fail;    //匹配失败了

 98         }

 99     }

100     return cnt;

101 }

102 

103 int main()

104 {

105     //freopen("e://input.txt","r",stdin);

106     int t, n;

107     scanf("%d",&t);

108     while(t--)

109     {

110         q=0;

111         node *tree=create();

112         tree->fail=tree;

113         scanf("%d",&n);

114         for(int i=0; i<n; i++)  //构建字典树

115         {

116             cin>>str;

117             len=str.size();

118             input(0,tree);

119         }

120         BFS(tree);  //设置fail指针

121         scanf("%s",tar);

122         printf("%d\n",search(0, tree));

123     }

124 

125     return 0;

126 }
MLE代码

 

你可能感兴趣的:(search)