• hdoj2896(AC自动机简单题)


    题目链接:https://vjudge.net/problem/HDU-2896

    题意:给出n个模式串(没有相同的模式串),模式串总长<=1e5。然后给出m个文本,文本总长<=1e7,求每个文本串中出现的模式串(最多3种)。


    思路:

      板子题。因为要输出文本串中出现的模式串编号,所以需要记录字典树中以每个结点为末字符的模式串编号(key数组)。trie数组的第二位开到了130(所有ascii码都有),因此输入字符串用到了scanf("%[^ ]",s),但它不吃换行符,要用getchar吃掉换行符。

      又因为每输入一个文本,查询时会破坏key数组,因此创建AC自动机时用key1来记录,每次用key1来更新key2,用key2去查询。

    AC code:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    const int maxn=1e5+5;
    const int maxs=1e4+5;
    int n,m,cnt,ans,trie[maxn][130],key1[maxn],key2[maxn],fail[maxn];
    int res[5],cnt1;
    char s[maxs];
    
    void build(char *s,int k){
        int len=strlen(s),u=0;
        for(int i=0;i<len;++i){
            int t=s[i];
            if(!trie[u][t]){
                ++cnt;
                memset(trie[cnt],0,sizeof(trie[cnt]));
                key1[cnt]=0,fail[0]=0;
                trie[u][t]=cnt;
            }
            u=trie[u][t];
        }
        key1[u]=k;
    }
    
    void get_fail(){
        queue<int> que;
        for(int i=0;i<130;++i){
            if(trie[0][i]){
                fail[trie[0][i]]=0;
                que.push(trie[0][i]);
            }
        }
        while(!que.empty()){
            int u=que.front();que.pop();
            for(int i=0;i<130;++i){
                if(trie[u][i]){
                    fail[trie[u][i]]=trie[fail[u]][i];
                    que.push(trie[u][i]);
                }
                else{
                    trie[u][i]=trie[fail[u]][i];
                }
            }
        }
    }
    
    void query(char *s){
        int len=strlen(s),u=0;
        for(int i=0;i<len;++i){
            int t=s[i];
            u=trie[u][t];
            for(int j=u;j&&key2[j]!=-1;j=fail[j]){
                if(key2[j]) res[++cnt1]=key2[j];
                key2[j]=-1;
            }
        }
    }
    
    int main(){
        scanf("%d",&n);
        getchar();
        cnt=0,ans=0;
        memset(trie[0],0,sizeof(trie[0]));
        key1[0]=0;
        for(int i=1;i<=n;++i){
            scanf("%[^
    ]",s);
            getchar();
            build(s,i);
        }
        fail[0]=0;
        get_fail();
        scanf("%d",&m);
        getchar();
        for(int i=1;i<=m;++i){
            for(int j=0;j<=cnt;++j)
                key2[j]=key1[j];
            scanf("%[^
    ]",s);
            getchar();
            cnt1=0;
            query(s);
            if(cnt1){
                ++ans;
                sort(res+1,res+cnt1+1);
                printf("web %d:",i);
                for(int j=1;j<=cnt1;++j)
                    printf(" %d",res[j]);
                printf("
    ");
            }
        }
        printf("total: %d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Air-WIFI使用方法
    libeasy代码学习:一次简单的TCP请求处理流程
    log_pipe日志收集分析系统介绍
    asp.net 项目在 IE 11 下出现 “__doPostBack”未定义 的解决办法
    用命令行实现“一键休眠”
    C#几个经常用到的字符串的截取
    MYSQL存储过程怎么写
    如何用myeclipse和eclipse搭建安卓开发环境
    C#随机生成不重复字符串
    Inno setup 简单打包教程
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/12491355.html
Copyright © 2020-2023  润新知