zoukankan      html  css  js  c++  java
  • HDU

    原题地址HDU - 3065

    题意:给出N个模式串(在ascii范围内(128)),再给你一个文本串 (2 e6 以内),输出存在的模式串以及出现次数 (计数可以重叠)

    思路:AC自动机啦,我们要会用last优化后ac-atomaton

    #include<bits/stdc++.h>
    const int M=2e6+10;
    const int N=100000+5;
    using namespace std;
    
    queue<int> q;
    int res[N];//记录结果
    struct AC_Automata{
        int tire[N][128];//字典树
        int val[N];//字符串结尾标记
        int fail[N];//失配指针
        int last[N];//last[i]=j表j节点表示的单词是i节点单词的后缀,且j节点是单词节点
        int tot;//编号
    
        void init(){//初始化0号点
            tot=1;
            val[0]=fail[0]=last[0]=0;
            memset(tire[0],0,sizeof(tire[0]));
        }
    
        void insert(char *s,int v){//构造trie与val数组,v需非0,表示一个单词节点
            int len=strlen(s);
            int root=0;
            for(int i=0;i<len;i++){
                int id=s[i];
                if(tire[root][id]==0){
                    tire[root][id]=tot;
                    memset(tire[tot],0,sizeof(tire[tot]));
                    val[tot++]=0;
                }
                root=tire[root][id];
            }
            val[root]=v;
        }
    
        void build(){//构造fail与last
            while(!q.empty()) q.pop();
            last[0]=fail[0]=0;
            for(int i=0;i<128;i++){
                int root=tire[0][i];
                if(root!=0){
                    fail[root]=0;
                    last[root]=0;
                    q.push(root);
                }
            }
    
            while(!q.empty()){//bfs求fail
                int k=q.front();
                q.pop();
                for(int i=0;i<128;i++){
                    int u=tire[k][i];
                    if(u==0)
                        continue;
                    q.push(u);
    
                    int v=fail[k];
                    while(v && tire[v][i]==0)
                        v=fail[v];
                    fail[u]=tire[v][i];
                    last[u]=val[fail[u]]?fail[u]:last[fail[u]];
                }
            }
        }
    
        void print(int i){//递归打印与结点i后缀相同的前缀节点编号
            if(val[i]){
                res[val[i]]++;
                print(last[i]);
            }
        }
    
        void query(char *s){//匹配
            int len=strlen(s);
            int j=0;
            for(int i=0;i<len;i++){
                int id=s[i];
                while(j && tire[j][id]==0)
                    j=fail[j];
                j=tire[j][id];
                if(val[j])
                    print(j);
                else if(last[j])
                    print(last[j]);
            }
        }
    }ac;
    char P[1005][100];
    char T[M];
    int main(){
        int n;
        while(scanf("%d",&n)!=EOF&&n){
            memset(res,0,sizeof(res));
            ac.init();
    
            for(int i=1;i<=n;i++){
                scanf("%s",P[i]);
                ac.insert(P[i],i);
            }
            ac.build();
    
            scanf("%s",T);
            ac.query(T);
            for(int i=1;i<=n;i++)
                if(res[i])
                    printf("%s: %d
    ",P[i],res[i]);
        }
        return 0;
    }
  • 相关阅读:
    还在使用golang 的map 做Json编码么?
    Golang 性能测试(2) 性能分析
    golang 性能测试 (1) 基准性能测试
    消息队列 NSQ 源码学习笔记 (五)
    消息队列 NSQ 源码学习笔记 (四)
    消息队列 NSQ 源码学习笔记 (三)
    消息队列 NSQ 源码学习笔记 (二)
    消息队列 NSQ 源码学习笔记 (一)
    你不知道的空格
    Supervisor 使用和进阶4 (Event 的使用)
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11377117.html
Copyright © 2011-2022 走看看