题意:
给出一些病毒的特征串,如果一个程序(或者将程序反转)中出现了某个病毒的特征串,则该程序被这个病毒感染了。给出若干病毒串,一个程序串,问改程序被多少种病毒感染了?
解法:
比赛的时候模板有bug,WA到死,竟然这个用了数月的模板之前还神奇的通过了N道自动机的题目,不可思议。。
一道非常裸的自动机,将程序串正反匹配一遍既得答案。
自动机节点结构如下:
1 struct node
2 {
3 unsigned long long bit[4];
4 struct node *nxt[26];
5 struct node *pre;
6 };
用位记录以当前节点为后缀的子串包含了多少种模式串,位压缩策略如下:
1 void setbit(unsigned long long bit[],int pos)
2 {
3 bit[pos/64]|=(1ll<<(pos%64));
4 }
自动机转移策略(计算前缀指针):
1 void makepre()
2 {
3 struct node *p=buf;
4 int s=-1,e=-1,i;
5 for(i=0;i<26;i++)
6 if(p->nxt[i])
7 {
8 p->nxt[i]->pre=p;
9 q[++e]=p->nxt[i];
10 }
11 else
12 p->nxt[i]=p;
13 while(s!=e)
14 {
15 p=q[++s];
16 for(i=0;i<4;i++)
17 (p->bit[i])|=(p->pre->bit[i]);
18 for(i=0;i<26;i++)
19 {
20 struct node *pre=p->pre;
21 while(!(pre->nxt[i])) pre=pre->pre;
22 if(p->nxt[i])
23 {
24 p->nxt[i]->pre=pre->nxt[i];
25 q[++e]=p->nxt[i];
26 }
27 else
28 p->nxt[i]=pre->nxt[i];
29 }
30 }
31 }
整个程序(这次就当重新修正下模板。。用标准C语言写下自动机):
1 # include <stdio.h>
2 # include <stdlib.h>
3 # define N 300000
4 # define root 0
5 # include <string.h>
6 struct node
7 {
8 unsigned long long bit[4];
9 struct node *nxt[26];
10 struct node *pre;
11 }buf[N];
12 char str[5200000],tstr[5200000];
13 int c;
14 struct node *q[N];
15 void clear(struct node *pos)
16 {
17 memset(pos->bit,0,sizeof(pos->bit));
18 memset(pos->nxt,NULL,sizeof(pos->nxt));
19 pos->pre=NULL;
20 }
21 void init()
22 {
23 c=1;
24 clear(buf);
25 }
26 void setbit(unsigned long long bit[],int pos)
27 {
28 bit[pos/64]|=(1ll<<(pos%64));
29 }
30 void insert(char *str,int id)
31 {
32 int i,len=strlen(str);
33 struct node *p=buf;
34 for(i=0;i<len;i++)
35 {
36 if(!(p->nxt[str[i]-'A']))
37 {
38 p->nxt[str[i]-'A']=&buf[c++];
39 clear(p->nxt[str[i]-'A']);
40 }
41 p=p->nxt[str[i]-'A'];
42 }
43 setbit(p->bit,id);
44 }
45 void makepre()
46 {
47 struct node *p=buf;
48 int s=-1,e=-1,i;
49 for(i=0;i<26;i++)
50 if(p->nxt[i])
51 {
52 p->nxt[i]->pre=p;
53 q[++e]=p->nxt[i];
54 }
55 else
56 p->nxt[i]=p;
57 while(s!=e)
58 {
59 p=q[++s];
60 for(i=0;i<4;i++)
61 (p->bit[i])|=(p->pre->bit[i]);
62 for(i=0;i<26;i++)
63 {
64 struct node *pre=p->pre;
65 while(!(pre->nxt[i])) pre=pre->pre;
66 if(p->nxt[i])
67 {
68 p->nxt[i]->pre=pre->nxt[i];
69 q[++e]=p->nxt[i];
70 }
71 else
72 p->nxt[i]=pre->nxt[i];
73 }
74 }
75 }
76 int match()
77 {
78 struct node *p=buf;
79 unsigned long long res[4];
80 int len=strlen(str),i,j,ans=0;
81 memset(res,0,sizeof(res));
82 for(i=0;i<len;i++)
83 {
84 p=p->nxt[str[i]-'A'];
85 for(j=0;j<4;j++)
86 res[j]|=(p->bit[j]);
87 }
88 strrev(str);
89 p=buf;
90 for(i=0;i<len;i++)
91 {
92 p=p->nxt[str[i]-'A'];
93 for(j=0;j<4;j++)
94 res[j]|=(p->bit[j]);
95 }
96 for(i=0;i<4;i++)
97 while(res[i])
98 {
99 ans+=(res[i]&1);
100 res[i]>>=1;
101 }
102 return ans;
103 }
104 void decompress()
105 {
106 int p=0,len=strlen(tstr),i;
107 for(i=0;i<len;i++)
108 {
109 if(tstr[i]=='[')
110 {
111 int j,num;
112 char ch;
113 for(j=i+1;j<len&&tstr[j]!=']';j++);
114 ch=tstr[j-1];
115 tstr[j-1]='\0';
116 num=atoi(tstr+i+1);
117 i=j;
118 while(num--)
119 str[p++]=ch;
120 }
121 else
122 str[p++]=tstr[i];
123 }
124 str[p]='\0';
125 }
126 int main()
127 {
128 int test;
129 scanf("%d",&test);
130 while(test--)
131 {
132 int n,i;
133 init();
134 scanf("%d",&n);
135 for(i=0;i<n;i++)
136 {
137 char tmp[1005];
138 scanf("%s",tmp);
139 insert(tmp,i);
140 }
141 makepre();
142 scanf("%s",tstr);
143 decompress();
144 printf("%d\n",match());
145 }
146 return 0;
147 }
148
149