hdu 3065 病毒侵袭持续中 (ac自动机)

题目链接

题意:给出n个病毒的模式串,问每个病毒串在文本串中出现了多少次。

思路:ac自动机。模式串只由大写字母组成。文本串是所有可视字符。 如果动态128会MLE.做法是换成静态数组写法,或者对于每次Search的时候,出现非大写字母的字符特判一下。

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年08月18日 星期四 00时17分38秒
  4File Name :code/hdu/3065.cpp
  5************************************************ */
  6#include <cstdio>
  7#include <cstring>
  8#include <iostream>
  9#include <algorithm>
 10#include <vector>
 11#include <queue>
 12#include <stack>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <deque>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27using namespace std;
 28const double eps = 1E-8;
 29const int dx4[4]={1,0,0,-1};
 30const int dy4[4]={0,-1,1,0};
 31const int inf = 0x3f3f3f3f;
 32const int sizTrie = 26;
 33map<int,int>mp;
 34char ill[1005][50];
 35struct Trie
 36{
 37    struct Node
 38    {
 39	Node *nxt[sizTrie];
 40	Node *fail;
 41	int cnt;
 42	int id;
 43	Node()
 44	{
 45	    for ( int i = 0 ; i < sizTrie; i++) nxt[i]=NULL;
 46	    cnt = 0 ;
 47	    id = 0 ;
 48	    fail = NULL;
 49	}
 50    };
 51    Node *root;
 52    void init()
 53    {
 54	root = new Node();
 55    }
 56    void Insert(char *s,int x)
 57    {
 58	int len = strlen(s);
 59	Node *u = root;
 60	for ( int i = 0 ; i < len ; i++ )
 61	{
 62	    int v = s[i]-'A';
 63	    if (u->nxt[v]==NULL) u->nxt[v] = new Node();
 64	    u = u->nxt[v];
 65	}
 66	u->cnt++;
 67	u->id = x;
 68//	cout<<"s:"<<s<<" cnt:"<< u->cnt <<endl;
 69    }
 70    void getFail()
 71    {
 72	root->fail = root;
 73	queue<Node*>Q;
 74	for ( int i = 0 ; i < sizTrie ; i++)
 75	{
 76	    if (root->nxt[i]==NULL)
 77		root->nxt[i] = root;
 78	    else
 79	    {
 80		root->nxt[i]->fail = root;
 81		Q.push(root->nxt[i]);
 82	    }
 83	}
 84	while (!Q.empty())
 85	{
 86	    Node * cur = Q.front();
 87	    Q.pop();
 88	    for ( int i = 0 ; i < sizTrie ; i++)
 89	    {
 90		if (cur->nxt[i]==NULL)
 91		    cur->nxt[i] = cur->fail->nxt[i];
 92		else
 93		{
 94		    cur->nxt[i]->fail = cur->fail->nxt[i];
 95		    Q.push(cur->nxt[i]);
 96		}
 97	    }
 98	}
 99    }
100	void Search(char *s)
101	{
102	    int len = strlen(s);
103	    Node *u = root;
104	    mp.clear();
105	    for ( int i = 0 ; i < len ; i++)
106	    {
107		if (s[i]<'A'||s[i]>'Z')
108		{
109		    u = root; //不要忘记,出现不可能被匹配的字符,相当于重新初始化了
110		    continue;
111		}
112		int v = s[i]-'A';
113		u = u->nxt[v];
114		Node * tmp = u;
115		while (tmp!=root)
116		{
117		    if (tmp->id)
118		    mp[tmp->id]++;
119		    tmp = tmp->fail;
120		}
121	    }
122	    for (auto it = mp.begin() ; it!=mp.end() ; it++)
123//		if (strcmp(ill[it->fst],"")!=0)
124		printf("%s: %d\n",ill[it->fst],it->sec);
125/*	    //sort(ans.begin(),ans.end());
126	    int siz = ans.size();
127	    cout<<"anszie:"<<ans.size()<<endl;
128	    for ( int i = 0 ; i < siz;  i++)
129	    {
130		printf("%s: %d\n",ill[ans[i].fst],ans[i].sec);
131	    }   */
132	}
133}ac;
134const int N=2E6+7;
135int n;
136char str[N];
137int main()
138{
139	#ifndef  ONLINE_JUDGE 
140	freopen("code/in.txt","r",stdin);
141  #endif
142	while (scanf("%d",&n)!=EOF)
143	{   
144	    ac.init();
145	    for ( int i = 1 ; i <= n ; i++)
146	    {
147		scanf("%s",ill[i]);
148		ac.Insert(ill[i],i);
149	    }
150	    ac.getFail();
151	    scanf("%s",str);
152	    //	cout<<"str:"<<str<<endl;
153	    ac.Search(str);
154	}
155  #ifndef ONLINE_JUDGE  
156  fclose(stdin);
157  #endif
158    return 0;
159}