fzu 2005 Computer Virus on Planet Pandora (The 35th ACM/ICPC Asia Regional Fuzhou Site) AC自动机

fzu 2005 Computer Virus on Planet Pandora (The 35th ACM/ICPC Asia Regional Fuzhou Site) AC自动机

题意:
给出一些病毒的特征串,如果一个程序(或者将程序反转)中出现了某个病毒的特征串,则该程序被这个病毒感染了。给出若干病毒串,一个程序串,问改程序被多少种病毒感染了?
解法:
比赛的时候模板有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 


你可能感兴趣的:(fzu 2005 Computer Virus on Planet Pandora (The 35th ACM/ICPC Asia Regional Fuzhou Site) AC自动机)