zoukankan      html  css  js  c++  java
  • HDU 2222 Keywords Search 【AC自动机】

    题目链接:【http://acm.hdu.edu.cn/showproblem.php?pid=2222】

    题意:给出很多小字符串,然后给出一个文本串,问文本串中包含多少个小字符串。也就是说如果文本串中出现了多次某个小字符串,则只算一次。

    题解:裸的AC自动机,首先利用小字符串建立一个Trie,然后再Trie上做KMP,使得为一个节点具有一个fail指针,其含义是,当文本串在某个节点失配时,则在Trie上找到根节点到这个节点的最长后缀的一个串,然后指向它。

    不断地匹配下去就行了。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 5e5 + 10;
    struct Aho_C
    {
        int next[maxn][26], fail[maxn], End[maxn];
        int root, L;
        int newnode()
        {
            for(int i = 0; i < 26; i++)
                next[L][i] = -1;
            End[L++] = 0;
            return L - 1;
        }
        void init()
        {
            L = 0;
            root = newnode();
        }
        void Insert(char buf[])
        {
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++)
            {
                if(next[now][buf[i] - 'a'] == -1)
                    next[now][buf[i] - 'a'] = newnode();
                now = next[now][buf[i] - 'a'];
            }
            End[now]++;
        }
        void Build()
        {
            queue<int>Q;
            fail[root] = root;
            for(int i = 0; i < 26; i++)
                if(next[root][i] == -1)
                    next[root][i] = root;
                else
                {
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            while( !Q.empty() )
            {
                int now = Q.front();
                Q.pop();
                for(int i = 0; i < 26; i++)
                    if(next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else
                    {
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                    }
            }
        }
        int Query(char buf[])
        {
            int len = strlen(buf);
            int now = root, res = 0;
            for(int i = 0; i < len; i++)
            {
                now = next[now][buf[i] - 'a'];
                int temp = now;
                while( temp != root )
                {
                    res += End[temp];
                    End[temp] = 0;
                    temp = fail[temp];
                }
            }
            return res;
        }
    }ac;
    char buf[maxn * 2];
    int main()
    {
        int T, n;
        scanf("%d", &T);
        while( T-- )
        {
            scanf("%d", &n);
            ac.init();
            for(int i = 0; i < n; i++)
            {
                scanf("%s", buf);
                ac.Insert(buf);
            }
            ac.Build();
            scanf("%s", buf);
            printf("%d
    ", ac.Query(buf));
        }
        return 0;
    }
    

      

  • 相关阅读:
    Python PEP8 编码规范中文版
    MySQL分区表
    mybatis缓存,包含一级缓存与二级缓存,包括ehcache二级缓存
    斐讯K2刷不死breed与第三方固件教程
    Mysql 多表连接查询 inner join 和 outer join 的使用
    mysql多表关联删除示例
    sublime Text 几款插件
    多进程vs多线程
    git 命令常用总结
    LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
  • 原文地址:https://www.cnblogs.com/pealicx/p/7603793.html
Copyright © 2011-2022 走看看