字符串---AC自动机

作者: 哟破赛呦 | 来源:发表于2019-01-17 17:51 被阅读12次

    求目标串中出现了几个模式串

    思路

    一、构建字典树
    二、构建fail指针
    三、串匹配

    例题

    HDU2222

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    namespace Trie{
        int next[500010][26], fail[500010], end[500010];//字典树,fail指针,单词末尾标记
        int root, L;//根节点,树节点计数
        int new_node(){
            for(int i = 0; i < 26; i++){
                next[L][i] = -1;
            }
            end[L++] = 0;
            return L-1;
        }
        void init(){
            L=0;
            root = new_node();
        }
        void insert(const 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'] = new_node();
                }
                now = next[now][buf[i]-'a'];
            }
            end[now]++;
        }
        void build(){//构建fail指针
            queue<int> que;
            fail[root] = root;
            for(int i = 0; i < 26; i++){
                if(next[root][i] == -1){
                    next[root][i] = root;//指向root说明没有
                }else{
                    fail[next[root][i]] = root;
                    que.push(next[root][i]);
                }
            }
            while(!que.empty()){
                int now = que.front();
                que.pop();
                for(int i = 0; i < 26; i++){
                    if(next[now][i] == -1){
                        next[now][i] = next[fail[now]][i]; //没有这个字符就去fail,方便遍历不用判断是否空
                    }else{
                        fail[next[now][i]] = next[fail[now]][i]; // 孩子的fail指针,往自己fail方向找
                        que.push(next[now][i]);
                    }
                }
            }
        }
        int query(const char buf[]){
            int len = strlen(buf);
            int now = root;
            int 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;
        }
    }
    char buf[1000010];
    int main(){
        int t,n;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            Trie::init();
            for(int i=0;i<n;i++){
                scanf("%s",buf);
                Trie::insert(buf);
            }
            Trie::build();
            scanf("%s",buf);
            printf("%d\n",Trie::query(buf));
        }
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:字符串---AC自动机

        本文链接:https://www.haomeiwen.com/subject/ylzidqtx.html