zoukankan      html  css  js  c++  java
  • hdu 2222 Keywords Search(ac自动机)

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

    题意:给你一系列子串,再给你一个主串问你主串一共有几个匹配子串

    原来使用字典树写的但数据有点大TLE了,然后就开始学习ac自动机了,ac自动机就像是多串匹配的kmp原理也是类似的。

    这题可以练一下手写ac自动机模版。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    using namespace std;
    const int M = 5e5 + 50;
    int Next[M][26] , fail[M] , End[M] , root , L , cnt;
    char str[60] , sl[M * 2];
    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 build(char s[]) {
        int len = strlen(s);
        int now = root;
        for(int i = 0 ; i < len ; i++) {
            int id = s[i] - 'a';
            if(Next[now][id] == -1) {
                Next[now][id] = newnode();
            }
            now = Next[now][id];
        }
        ++End[now];
    }
    void get_fail() {
        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]);
                }
            }
        }
    }
    void match(char s[]) {
        int now = root;
        int len = strlen(s);
        for(int i = 0 ; i < len ; i++) {
            int id = s[i] - 'a';
            now = Next[now][id];
            int temp = now;
            while(temp != root) {
                cnt += End[temp];
                End[temp] = 0;
                temp = fail[temp];
            }
        }
    }
    int main()
    {
        int t;
        scanf("%d" , &t);
        while(t--) {
            int n;
            scanf("%d" , &n);
            init();
            for(int i = 0 ; i < n ; i++) {
                scanf("%s" , str);
                build(str);
            }
            get_fail();
            scanf("%s" , sl);
            cnt = 0;
            match(sl);
            printf("%d
    " , cnt);
        }
        return 0;
    }
    
  • 相关阅读:
    删除查询出以外的数据
    查询头3条
    查询共多少条记录
    Linq查询非泛型集合要指定Student类型(比如List)
    Linq to 泛型集合查询集合包括大写M和年龄小于等于18
    LINQ查询字符串判断是否大写
    LINQ查询数组里面是否包含某值
    Lambda表达式
    构建之法(四)
    构建之法(三)
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6080469.html
Copyright © 2011-2022 走看看