【HDU3065】 病毒侵袭持续中(AC自动机)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10504 Accepted Submission(s): 3701Problem Description小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?
Input第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
Output按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
Sample Input3 AA BB CC ooxxCC%dAAAoen....END
Sample OutputAA: 2 CC: 1HintHit: 题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。 计数策略也可一定程度上从Sample中推测。
【分析】
做了BZOJ2434,这题就显得很简单了。反正我的做法跟上一题其实差不多,就是先建AC自动机,然后求DFS序,再走一遍目标串,打好标记,最后求一个区间的和即可。不过目测其他慢一点的方法也是可以的。
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 #define Maxn 100100 9 #define Maxl 2000010 10 #define Ml 60 11 #define Mn 1010 12 13 char ss[Mn][Ml]; 14 char s[Maxl]; 15 int p[Maxn],c[Maxn]; 16 int n; 17 18 struct hp 19 { 20 int x,y,next; 21 }qy[Maxn];int al; 22 23 struct node 24 { 25 int son[30],cnt,fail; 26 int num,rt; 27 }t[Maxn];int tot; 28 29 int first[Maxn]; 30 31 void ins(int x,int y) 32 { 33 qy[++al].x=x;qy[al].y=y; 34 qy[al].next=first[x];first[x]=al; 35 } 36 37 void upd(int x) 38 { 39 t[x].cnt=0; 40 memset(t[x].son,0,sizeof(t[x].son)); 41 } 42 43 void read_trie(int x) 44 { 45 scanf("%s",ss[x]+1); 46 int len=strlen(ss[x]+1); 47 int now=0; 48 for(int j=1;j<=len;j++) 49 { 50 int ind=ss[x][j]-'A'+1; 51 if(!t[now].son[ind]) 52 t[now].son[ind]=++tot,upd(tot); 53 now=t[now].son[ind]; 54 if(j==len) t[now].cnt++,p[x]=now; 55 } 56 } 57 58 queue<int > q; 59 void build_AC() 60 { 61 int i,j,x,y; 62 while(!q.empty()) q.pop(); 63 q.push(0); 64 while(!q.empty()) 65 { 66 x=q.front(); 67 y=t[x].fail; 68 for(j=1;j<=26;j++) 69 { 70 if(t[x].son[j]) 71 { 72 q.push(t[x].son[j]); 73 t[t[x].son[j]].fail=x?t[y].son[j]:x; 74 ins(t[t[x].son[j]].fail,t[x].son[j]); 75 } 76 else t[x].son[j]=t[y].son[j]; 77 } 78 q.pop(); 79 } 80 } 81 82 void dfs(int x) 83 { 84 t[x].num=++al;t[x].rt=t[x].num; 85 for(int i=first[x];i;i=qy[i].next) 86 dfs(qy[i].y),t[x].rt=t[qy[i].y].rt; 87 } 88 89 void dfs2(int x) 90 { 91 scanf("%s",s+1); 92 int len=strlen(s+1); 93 int now=0; 94 for(int j=1;j<=len;j++) 95 { 96 if(s[j]<'A'||s[j]>'Z') {now=0;continue;} 97 int ind=s[j]-'A'+1; 98 now=t[now].son[ind]; 99 c[t[now].num]++; 100 } 101 } 102 103 void init() 104 { 105 memset(first,0,sizeof(first)); 106 tot=0;upd(0); 107 for(int i=1;i<=n;i++) 108 { 109 read_trie(i); 110 } 111 al=0;build_AC();al=0; 112 dfs(0); 113 memset(c,0,sizeof(c)); 114 dfs2(0);c[0]=0; 115 for(int i=2;i<=al;i++) c[i]=c[i-1]+c[i]; 116 for(int i=1;i<=n;i++) 117 { 118 int ans=0; 119 ans=c[t[p[i]].rt]-c[t[p[i]].num-1]; 120 if(ans!=0) printf("%s: %d\n",ss[i]+1,ans); 121 } 122 } 123 124 int main() 125 { 126 while(scanf("%d",&n)!=EOF) 127 { 128 init(); 129 } 130 return 0; 131 }
2016-06-17 13:46:45