• 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;
    }
    

      

  • 相关阅读:
    Spring框架——JdbcTemplate(Spring对Jdbc的封装)
    Spring框架——批处理(batch)和事务(Transaction)
    Spring框架——AOP(面向切面编程)详解
    Spring框架——关于IOC容器和注解的36个小实验
    学习新技术的 10 个建议
    解决 PHP Fatal error: Call-time pass-by-reference has been removed
    mysql下float类型使用一些误差详解
    windows 如何查看端口占用情况
    插件机制
    .net/c#常用框架/中间件简介
  • 原文地址:https://www.cnblogs.com/pealicx/p/7603793.html
Copyright © 2020-2023  润新知