zoukankan      html  css  js  c++  java
  • AC自动机

    Problem's Link

    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] = '';
    }
    
    
    int main() {
        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
    ", ans );
        }
        return 0;
    }

     

  • 相关阅读:
    String类的常用方法(P小写)
    二维数组:判断是否有目标数
    java实现输入年份判断在哪一天(正则表达式待改进)
    Java实现八进制正整数转化为十进制数
    时钟和定时器
    电路的频率响应---带宽的定义
    stm32两轮平衡车资料
    二阶常系数齐次线性微分方程的解法
    同步积分
    陀螺仪信号解调
  • 原文地址:https://www.cnblogs.com/crazyacking/p/4653984.html
Copyright © 2011-2022 走看看