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

    传送门

    解题思路

    AC自动机,是解决多模匹配问题的算法,是字典树与kmp结合的算法,可以解决许多子串在文本串中出现的次数等信息。关键是实现一个fail指针,是指向更靠上的前缀相同字母,从而可以实现在文本串中跳的操作。

    代码

        #include<iostream>
        #include<cstdio>
        #include<algorithm>
        #include<cstring>
        #include<queue>
    
        using namespace std;
        const int MAXN = 1e6+5;
    
        int n,ans,cnt;
    
        struct Tree{
            int vis[30],fail,end;
        }AC[MAXN];
    
        inline void build(string S){
            int len=S.length();
            int now=0;
            for(register int i=0;i<len;i++){
                if(!AC[now].vis[S[i]-'a'+1])
                    AC[now].vis[S[i]-'a'+1]=++cnt;
                now=AC[now].vis[S[i]-'a'+1];
            }
            AC[now].end++;
        }
    
        inline void Get_fail(){
            queue<int> Q;
            for(register int i=1;i<=26;i++)
                if(AC[0].vis[i]){
                    AC[AC[0].vis[i]].fail=0;
                    Q.push(AC[0].vis[i]);
                }
            while(Q.size()){
                int x=Q.front();Q.pop();
                for(register int i=1;i<=26;i++){
                    if(AC[x].vis[i]){   //如果这个字母存在,子节点fail指针指向它上一层这个字母的fail所指向的字母,有点难理解,要画图
                        AC[AC[x].vis[i]].fail=AC[AC[x].fail].vis[i];
                        Q.push(AC[x].vis[i]);
                    }
                    else AC[x].vis[i]=AC[AC[x].fail].vis[i];
                }
            }
        }
    
        inline int Query(string S){
            int len=S.length();
            int now=0,t;
            for(register int i=0;i<len;i++){
                now=AC[now].vis[S[i]-'a'+1];
                for(t=now;t && AC[t].end!=-1;t=AC[t].fail){
                    ans+=AC[t].end;
                    AC[t].end=-1;
                }
            }
            return ans;
        }
    
        int main(){
            cin>>n;
            for(register int i=1;i<=n;i++){
                string s;
                cin>>s;
                build(s);
            }
            AC[0].fail=0;
            Get_fail();
            string s;
            cin>>s;
            cout<<Query(s)<<endl;
            return 0;
        }
  • 相关阅读:
    Android课程---Activity的跳转与传值(转自网上)
    Android课程---Activity中保存和恢复用户状态
    Android课程---Activity 的生命周期
    Android课程---Activity的创建
    初学JAVA随记——练习写代码(8种数据类型)
    资料——UTF-8
    资料——ASCII码
    初学JAVA随记——8bit(1byte)的取值范围是+127到—128
    初学JAVA随记——变量与常量
    进制转换
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676953.html
Copyright © 2011-2022 走看看