zoukankan      html  css  js  c++  java
  • HDU 2222 Keywords Search (AC自动机模板题)

    一组数据:

    1

    3

    sss

    sss

    sss

    sss

    ans:3

    #include <cstdio>
    #include <cstdlib>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    
    //MAX_NODE = StringNumber * StringLength
    const int MAX_NODE = 10100 * 50;
    //节点个数,一般字符形式的题26个
    const int CHILD_NUM = 26;
    const int MAXN = 1000100;
    
    struct ACAutomaton {
        //每个节点的儿子,即当前节点的状态转移
        int chd[MAX_NODE][CHILD_NUM];
        //记录题目给的关键数据
        int val[MAX_NODE];
        //传说中的fail指针
        int fail[MAX_NODE];
        //队列,用于广度优先计算fail指针
        int Q[MAX_NODE];
        //字母对应的ID
        int ID[128];
        //已使用节点个数
        int sz;
    
        //初始化,计算字母对应的儿子ID,如:'a'->0 ... 'z'->25
        void Initialize() {
            fail[0] = 0;
            for (int i = 0 ; i < CHILD_NUM ; i ++) {
                ID[i+'a'] = i;
            }
        }
        //重新建树需先Reset
        void Reset() {
            memset(chd[0] , 0 , sizeof(chd[0]));
            memset( val, 0, sizeof(val) );
            sz = 1;
        }
        //将权值为key的字符串a插入到trie中
        void Insert(char *a, int key) {
            int p = 0;
            for ( ; *a ; a ++) {
                int c = ID[(int)(*a)];
                if (!chd[p][c]) {
                    memset(chd[sz] , 0 , sizeof(chd[sz]));
                    val[sz] = 0;
                    chd[p][c] = sz ++;
                }
                p = chd[p][c];
            }
            val[p] += key;
        }
        //建立AC自动机,确定每个节点的权值以及状态转移
        void Construct() {
            int *s = Q , *e = Q;
            for (int i = 0 ; i < CHILD_NUM ; i ++) {
                if (chd[0][i]) {
                    fail[ chd[0][i] ] = 0;
                    *e ++ = chd[0][i];
                }
            }
            while (s != e) {
                int u = *s++;
                for (int i = 0 ; i < CHILD_NUM ; i ++) {
                    int &v = chd[u][i];
                    if (v) {
                        *e ++ = v;
                        fail[v] = chd[ fail[u] ][i];
                        //以下一行代码要根据题目所给val的含义来写
                        //val[v] |= val[ fail[v] ];
                    } else {
                        v = chd[ fail[u] ][i];
                    }
                }
            }
        }
    
        int Search( char *str )
        {
            int ans = 0;
            int i = 0;
            int p = 0;
            while ( str[i] )
            {
                int c = ID[ (int)(str[i]) ];
                while ( p != 0 && !chd[p][c] ) p = fail[p];
                if ( chd[p][c] ) p = chd[p][c];
                else p = 0;
    
                int tmp = p;
                while( tmp != 0 && val[tmp] != 0 )
                {
                    ans += val[tmp];
                    val[tmp] = 0;
                    tmp = fail[tmp];
                }
                ++i;
            }
            return ans;
        }
    }AC;
    
    int N;
    char str[MAXN];
    
    int main()
    {
        AC.Initialize();
        int T;
        scanf( "%d", &T );
        while ( T-- )
        {
            char tmp[60];
            scanf( "%d", &N );
            AC.Reset();
            for ( int i = 0; i < N; ++i )
            {
                scanf( "%s", tmp );
                AC.Insert( tmp, 1 );
            }
            AC.Construct();
            scanf( "%s", str );
            printf( "%d
    ", AC.Search(str) );
        }
        return 0;
    }
  • 相关阅读:
    后端框架:SpringBoot+Mybatis+Dubbox(zookeeper+dubbo-admin)
    java代码执行mysql存储过程
    SpringBoot整合Junit
    摘要算法之MD5
    java如何控制下载的文件类型是txt还是doc?如何将文件名返回给前端?Content-disposition
    Android Atuido 连接模拟器
    verilog CRC 校验
    Altium Designer(AD软件)如何导出gerber文件
    SpringBoot集成mybatisplus
    C++ | 通过智能指针实现资源管理
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3364885.html
Copyright © 2011-2022 走看看