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;
    }
  • 相关阅读:
    【NOI2015】品酒大会 SAM
    4566: [Haoi2016]找相同字符 SAM
    3709: [PA2014]Bohater 贪心
    1925: [Sdoi2010]地精部落 dp, 抖动子序列
    4205: 卡牌配对 最大流+建图技巧
    留言板
    self-introduction
    最近比赛
    STOI补番队胡策
    BZOJ 3503: [Cqoi2014]和谐矩阵( 高斯消元 )
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11377117.html
Copyright © 2011-2022 走看看