zoukankan      html  css  js  c++  java
  • 【HDOJ2222】Keywords Search(AC自动机)

    problem

    • 给定n(< 1e4)个长度不超过50的单词(模式串)和一篇长为m(< 1e6)的文章(主串)。
    • 求多少个单词在文章中出现了。

    solution

    • AC自动机模板
      1、将所有模式串构建成字典树
      2、求出nxt数组,其中nxt[i]表示匹配到i节点i的转移边都不能匹配了,满足最长前后缀关系的新节点。
      3、继续匹配

    codes

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn = 5e5+5;
    
    int tot, tire[maxn][30], val[maxn], nxt[maxn];
    void build(){
        tot = 1;
        memset(val,0,sizeof(val));
        memset(tire,0,sizeof(tire));
    }
    void insert(char *s){
        int u = 1, len = strlen(s);
        for(int i = 0; i < len; i++){
            int c = s[i]-'a';
            if(tire[u][c]==0)tire[u][c] = ++tot;
            u = tire[u][c];
        }
        val[u]++;
        return ;
    }
    int find(char *s){
        int ans = 0;
        int u = 1, len = strlen(s);
        for(int i = 0; i < len; i++){
            int c = s[i]-'a';
            int k = tire[u][c];
            while(k > 1){
                ans += val[k];
                val[k] = 0;
                k = nxt[k];
            }
            u = tire[u][c];
        }
        return ans;
    }
    void genfail(){
        for(int i = 0; i < 26; i++)tire[0][i] = 1;
        queue<int>q;
        q.push(1); nxt[1] = 0;
        while(q.size()){
            int u = q.front();  q.pop();
            for(int i = 0; i < 26; i++){
                if(!tire[u][i])tire[u][i] = tire[nxt[u]][i];//如果不存在u->i转移边,就直接回到第一个满足字符i的节点
                else{
                    q.push(tire[u][i]);
                    nxt[tire[u][i]] = tire[nxt[u]][i];
                }
            }
        }
    }
    
    char s[maxn<<1];
    int main(){
        int T;  scanf("%d",&T);
        while(T--){
            build();
            int n;  scanf("%d",&n);
            for(int i = 1; i <= n; i++){
                scanf("%s",s);
                insert(s);
            }
            genfail();
            scanf("%s",s);
            printf("%d
    ",find(s));
        }
        return 0;
    }
  • 相关阅读:
    java(5)流程控制n阶乘各位和
    java(4)运算符
    java(3)
    java(2)
    java(1)
    语音识别,图片识别(1)
    java实现——005从尾到头打印链表
    java实现——004替换空格
    java实现——003二维数组中的查找
    java实现——035第一个只出现一次的字符
  • 原文地址:https://www.cnblogs.com/gwj1314/p/10200108.html
Copyright © 2011-2022 走看看