• AC自动机 P3808 P3796


    第一次写AC自动机##

    简单版的这道题可以在进行匹配的时候剪一下枝,应为之前比配过了,不用在匹配了。

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    const int MAXN=1e6+10;
    queue<int> que;
    
    struct AC{
        int tr[MAXN][26],fail[MAXN],val[MAXN],tot;
    
        void insert(char *s){
            int n=strlen(s+1),p=0;
            for(int i=1;i<=n;i++){
                if(!tr[p][s[i]-'a'])
                    tr[p][s[i]-'a']=++tot;
                p=tr[p][s[i]-'a'];
            }
            val[p]++;
        }
    
        void getfail(){
            while(!que.empty()) que.pop();
            for(int i=0;i<26;i++)
                if(tr[0][i])
                    que.push(tr[0][i]);
            while(!que.empty()){
                int u=que.front();que.pop();
                for(int i=0;i<26;i++)
                    if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],que.push(tr[u][i]);
                    else tr[u][i]=tr[fail[u]][i];
            }
            // for(int i=0;i<=tot;i++) cout<<fail[i]<<" ";cout<<endl;
            // for(int i=0;i<=tot;i++) cout<<val[i]<<" ";cout<<endl;
        }
    
        int ask(char *s){
            int n=strlen(s+1),p=0,ans=0;
            for(int i=1;i<=n;i++){
                p=tr[p][s[i]-'a'];
                for(int t=p;t&&val[t]!=-1;t=fail[t])
                    ans+=val[t],val[t]=-1;
            }
            return ans;
        }
    }ac;
    
    int n;
    char s[MAXN];
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            ac.insert(s);
        }
        ac.getfail();
        scanf("%s",s+1);
        int ans=ac.ask(s);
        printf("%d
    ",ans);
        return 0;
    }
    

    加强版的题,就不能剪枝了,因为要求出每个模式串出现的次数。

    可以在 (trie) 的末节点上记录该串的 (id) 然后每次匹配到就给它++就行了。

    #include <iostream>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    const int MAXN=1e6+10;
    queue<int> que;
    int cnt[160],ans,n;
    char s[160][100],str[MAXN];
    
    struct AC{
        int tr[16000][26],fail[MAXN],val[MAXN],tot;
    
        void init(){
            memset(cnt,0,sizeof(cnt));
            memset(tr,0,sizeof(tr));
            memset(fail,0,sizeof(fail));
            memset(val,0,sizeof(val));
            tot=0;
            ans=0;
        }
    
        void insert(char *s,int id){
            int n=strlen(s+1),p=0;
            for(int i=1;i<=n;i++){
                if(!tr[p][s[i]-'a']) tr[p][s[i]-'a']=++tot;
                p=tr[p][s[i]-'a'];
            }
            val[p]=id;
        }
    
        void getfail(){
            while(!que.empty()) que.pop();
            for(int i=0;i<26;i++)
                if(tr[0][i]) que.push(tr[0][i]);
            while(!que.empty()){
                int u=que.front();que.pop();
                for(int i=0;i<26;i++)
                    if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],que.push(tr[u][i]);
                    else tr[u][i]=tr[fail[u]][i];
            }
        }
    
        void ask(char *s){
            int n=strlen(s+1),p=0;
            for(int i=1;i<=n;i++){
                p=tr[p][s[i]-'a'];
                for(int t=p;t;t=fail[t])
                    if(val[t]) cnt[val[t]]++,ans=max(ans,cnt[val[t]]);
            }
        }
    }ac;
    
    int main(){
        while(~scanf("%d",&n)){
            if(!n) break;
            ac.init();
            for(int i=1;i<=n;i++) 
                scanf("%s",s[i]+1),
                ac.insert(s[i],i);
            ac.getfail();
            scanf("%s",str+1);
            ac.ask(str);
            printf("%d
    ",ans);
            for(int i=1;i<=n;i++) if(cnt[i]==ans) printf("%s
    ",s[i]+1);
        }
        return 0;
    }
    
  • 相关阅读:
    linux JAVA JDK环境配置
    逍遥语录
    php常用函数集
    使用uGUI系统玩转标准俄罗斯方块
    Unity3D中uGUI事件系统简述及使用方法总结
    JAVA笔记-如何将百万级数据高效的导出到Excel表单
    简单的异步Socket实现——SimpleSocket_V1.1
    Netty4.x中文教程系列(六) 从头开始Bootstrap
    Unity3D中简单的C#异步Socket实现
    基于Spring框架的简单多数据源切换解决办法
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/11771700.html
Copyright © 2020-2023  润新知