1. 程式人生 > >HDU-2222 Keywords Search 字符串問題 AC自動機

HDU-2222 Keywords Search 字符串問題 AC自動機

tex cnblogs key .html 開始 mit name 都是 root

題目鏈接:https://cn.vjudge.net/problem/HDU-2222

題意

給一些關鍵詞,和一個待查詢的字符串
問這個字符串裏包含多少種關鍵詞

思路

AC自動機模版題咯
註意一般情況不需要修改build方法,就像kmp裏的getfail一樣
一般的題目就是改改insert,query

一開始寫的模版總是有問題,懶得改了
直接找的kuangbin的模版【原創】AC自動機小結
註意數組和指針的效率差不了多少,此題同一個算法的指針形式(296ms)比數組(187ms)慢110ms

說實在的,數組寫法就是優雅。
網上那些指針的看著就難受,明明是好好的邏輯,變量名都是pqrvtxy,搞的跟被混淆了一樣。
改了兩套沒一個舒服的,真難受。

提交過程

AC

代碼

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int ACSize=500000+20;
const int maxitem=26, maxn=1e4+20, maxword=50+20, maxl=1e6+20;
char word[maxword], line[maxl];
struct Trie{
    int next[ACSize][26], fail[ACSize], cnt[ACSize];
    int root, total;
    int newnode(void){
        for(int pos=0; pos<maxitem; pos++)
            next[total][pos]=-1;
        cnt[total]=0;
        return total++;
    }

    void init(){
        total=0;
        root=newnode();
    }

    void insert(char buf[]){
        int now=root;
        for(int i=0; buf[i]; i++){
            int pos=buf[i]-‘a‘;
            if(next[now][pos]==-1)
                next[now][pos]=newnode();
            now=next[now][pos];
        }
        cnt[now]++;
    }

    void build(void){
        queue<int> que;
        fail[root]=root;
        for(int i=0; i<maxitem; i++)
            if(next[root][i]==-1)
                next[root][i]=root;
            else{
                fail[next[root][i]]=root;
                que.push(next[root][i]);
            }

        while(!que.empty()){
            int now=que.front(); que.pop();

            for(int pos=0; pos<maxitem; pos++)
                if(next[now][pos]==-1)
                    next[now][pos]=next[fail[now]][pos];
                else{
                    fail[next[now][pos]]=next[fail[now]][pos];
                    que.push(next[now][pos]);
                }
        }
    }

    int query(char buf[]){
        int now=root, res=0;
        for(int i=0; buf[i]; i++){
            int pos=buf[i]-‘a‘;
            now=next[now][pos];
            for (int tmp=now; tmp!=root && cnt[tmp]!=-1; tmp=fail[tmp]){
                res+=cnt[tmp];
                cnt[tmp]=-1;            // 註意此處,找到了就不要找第二次了,直接刪除即可
            }
        }return res;
    }

    void debug(void){
        for(int i=0; i<total; i++){
            printf("id=%3d, fail=%3d, end=%3d  [", i, fail[i], cnt[i]);
            for(int j=0; j<maxitem; j++)
                printf("%2d", next[i][j]);
            printf("]\n");
        }
    }
}AC;

int main(void){
    int T, n;

    scanf("%d", &T);
    while (T--){
        AC.init();
        scanf("%d", &n);
        for (int i=0; i<n; i++){
            scanf("%s", word);
            AC.insert(word);
        }AC.build();

        scanf("%s", line);
        printf("%d\n", AC.query(line));
    }

    return 0;
}
Time Memory Length Lang Submitted
187ms 27744kB 2369 G++ 2018-08-02 16:16:21

HDU-2222 Keywords Search 字符串問題 AC自動機