zoukankan      html  css  js  c++  java
  • hdu2222 (AC自动机模板)

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

    学习出:https://bestsort.cn/2019/04/28/402/

    主要是fail的建立。在跳的过程就是不断跳fail,而不是跳到一个fail再往下!!

    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<string>
    using namespace std;
    typedef long long ll;
    const int M=2e6+6;
    
    int trie[M][26]; //字典树
    int cntword[M];  //记录该单词出现次数
    int fail[M];     //失败时的回溯指针
    int cnt=0;
    
    void insert(string s){
        int root = 0;
        for(int i=0;i<s.size();i++){
            int next = s[i] - 'a';
            if(!trie[root][next])
                trie[root][next] = ++cnt;
            root = trie[root][next];
        }
        cntword[root]++;      //当前节点单词数+1
    }
    void getfail(){
        queue <int>q;
        for(int i=0;i<26;i++){      //将第二层所有出现了的字母扔进队列
            if(trie[0][i]){
                fail[trie[0][i]] = 0;
                q.push(trie[0][i]);
            }
        }
    
    //fail[now]    ->当前节点now的失败指针指向的地方
    ////tire[now][i] -> 下一个字母为i+'a'的节点的下标为tire[now][i]
        while(!q.empty()){
            int now = q.front();
            q.pop();
    
            for(int i=0;i<26;i++){      //查询26个字母
                if(trie[now][i]){
                    //如果有这个子节点为字母i+'a',则
    //让这个节点的失败指针指向(((他父亲节点)的失败指针所指向的那个节点)的下一个节点)
                    //有点绕,为了方便理解特意加了括号
    
                    fail[trie[now][i]] = trie[fail[now]][i];
                    q.push(trie[now][i]);
                }
                else//否则就让当前节点的这个子节点
                    //指向当前节点fail指针的这个子节点
                    trie[now][i] = trie[fail[now]][i];
            }
        }
    }
    
    
    int query(string s){
        int now = 0,ans = 0;
        for(int i=0;i<s.size();i++){    //遍历文本串
            now = trie[now][s[i]-'a'];  //从s[i]点开始寻找
            for(int j=now;j && cntword[j]!=-1;j=fail[j]){
                //一直向下寻找,直到匹配失败(失败指针指向根或者当前节点已找过).
                ans += cntword[j];
                cntword[j] = -1;    //将遍历国后的节点标记,防止重复计算
            }
        }
        return ans;
    }
    
    void Clear(){
        for(int i=0;i<=cnt;i++){
            for(int j=0;j<26;j++)
                trie[i][j]=0;
            cntword[i]=0;
            fail[i]=0;
        }
            
    } 
    int n,t;
    int main(){
        
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin>>t;
        while(t--){
            cin>>n;
            string s;
            for(int i=1;i<=n;i++){
                
                cin>>s;
                insert(s);
            }
            fail[0]=0;
            getfail();
            cin>>s;
            cout<<query(s)<<endl;
            Clear();
        } 
        return 0;
    }
    
    
    /*
    5
    ash
    shex
    bcd
    sha
    sh
    ashe
    
    
    2
    */
    View Code
  • 相关阅读:
    十个男人看了,九个成了富人
    win7下编译安装osgearth
    gdal源码编译安装
    win7下编译boost库总结
    everything && executor
    cursor:hand与cursor:pointer的区别介绍
    web程序记录当前在线人数
    汉字转拼音
    40多个非常有用的Oracle 查询语句
    asp.net 使用IHttpModule 做权限检查 登录超时检查(转)
  • 原文地址:https://www.cnblogs.com/starve/p/12255729.html
Copyright © 2011-2022 走看看