AC自动机 - 多模式串的匹配 --- HDU 3695 Computer Virus on Planet Pandora(模板题)

 Computer Virus on Planet Pandora

Problem's Link:  http://acm.hdu.edu.cn/showproblem.php?pid=3695  


 

Mean: 

有n个模式串和一篇文章,统计有多少模式串在文章中出现。(正反统计两次)

analyse:

好久没写AC自动机了,回顾一下AC自动机的知识。

本题在构造文章的时候需要仔细一点,其他没什么Trick,和普通AC自动机做法一样。(build Trie  --->  build Fail_Ptr ---> matching_and_count).

Time complexity: O(N*L+M)

 

Source code: 

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-07-19-10.29
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define  LL long long
#define  ULL unsigned long long
using namespace std;

const int M = 6000005;
class node
{
public:
      bool flag;
      node *fail, *next[26];
      node()
      {
            flag = false;
            fail = NULL;
            memset( next, NULL, sizeof next );
      }
};
node *root;
queue<node*> q;
char s[M], str[M];

void Insert( char *str ) // build Trie-Tree
{
      node *p = root;
      int i = 0, index;
      while( str[i] )
      {
            index = str[i] - 'A';
            if( p->next[index] == NULL )
                  p->next[index] = new node();
            p = p->next[index];
            ++i;
      }
      p->flag = true;
}

void build_ac_automation( node *root ) // build fail ptr
{
      root->fail = NULL;
      while( !q.empty() ) q.pop();
      q.push( root );
      while( !q.empty() )
      {
            node *temp = q.front(); q.pop();
            node *p = NULL;
            for( int i = 0; i < 26; ++i )
            {
                  if( temp->next[i] != NULL )
                  {
                        if( temp == root ) temp->next[i]->fail = root;
                        else
                        {
                              p = temp->fail;
                              while( p != NULL )
                              {
                                    if( p->next[i] != NULL )
                                    {
                                          temp->next[i]->fail = p->next[i];
                                          break;
                                    }
                                    p = p->fail;
                              }
                              if( p == NULL ) temp->next[i]->fail = root;
                        }
                        q.push( temp->next[i] );
                  }
            }
      }
}


int query( node *root )  // mathing and count
{
      node *p = root;
      int i = 0, ans = 0, index;
      while( str[i] )
      {
            index = str[i] - 'A';
            while( p->next[index] == NULL && p != root )
                  p = p->fail;
            p = p->next[index];
            if( p == NULL )
                  p = root;
            node *temp = p;
            while( temp != root && temp->flag )
            {
                  ans++;
                  temp->flag = false;
                  temp = temp->fail;
            }
            i++;
      }
      return ans;
}


inline void build_str( char *s )
{
      int len = strlen( s ), cnt = -1;
      for( int i = 0; i < len; ++i )
      {
            if( s[i] >= 'A' && s[i] <= 'Z' )
            {
                  str[++cnt] = s[i];
                  continue;
            }
            if( s[i] == '[' )
            {
                  ++i;
                  int num = 0;
                  for( ; s[i] >= '0' && s[i] <= '9'; ++i )
                  {
                        num = num * 10 + ( s[i] - '0' );
                  }
                  char ch = s[i];
                  ++i;
                  for( int j = 1; j <= num; ++j )
                        str[++cnt] = ch;
            }
      }
      str[++cnt] = '\0';
}


int main()
{
//      freopen("C:\\Users\\crazyacking\\Desktop\\cin.txt","r",stdin);
//      freopen("C:\\Users\\crazyacking\\Desktop\\cout.txt","w",stdout);
      ios_base::sync_with_stdio( false );
      cin.tie( 0 );
      int Cas;
      scanf( "%d", &Cas );
      while( Cas-- )
      {
            root = new node();
            int n;
            scanf( "%d", &n );
            while( n-- )
            {
                  scanf( "%s", s );
                  Insert( s );
            }
            build_ac_automation( root );
            scanf( "%s", s );
            build_str( s );
            int ans = query( root );
            strrev( str );
            ans += query( root );
            printf( "%d\n", ans );
      }
      return 0;
}
/*

*/

  

你可能感兴趣的:(AC自动机)