zoukankan      html  css  js  c++  java
  • [模板][P3808]AC自动机(简单版)

    Description:

    求n个模式串中有几个在文本串中出现

    Solution:

    模板,详见代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int mxn=1e7+5;
    char str[mxn],p[80];
    queue<int > q;
    
    namespace Trie {
        int tot,fail[mxn],val[mxn];
        int t[mxn][26];
        void ins(char *s) {
            int len=strlen(s),u=0;
            for(int i=0;i<len;++i) {
                if(!t[u][s[i]-'a']) t[u][s[i]-'a']=++tot;
                u=t[u][s[i]-'a'];
            }
            ++val[u];
        };
        void build() {
            for(int i=0;i<26;++i) 
                if(t[0][i]) fail[t[0][i]]=0,q.push(t[0][i]);
            while(!q.empty()) {
                int u=q.front(); q.pop();
                for(int i=0;i<26;++i) {
                    if(t[u][i]) fail[t[u][i]]=t[fail[u]][i],q.push(t[u][i]);
                    else t[u][i]=t[fail[u]][i]; //类似于路径压缩的优化
                }
            }	
        };
        int query(char *s) {
            int len=strlen(s),u=0,ans=0;
            for(int i=0;i<len;++i) {
                u=t[u][s[i]-'a']; //每次从大到小统计文本串以第i个字符结束的所有串
                for(int v=u;val[v]!=-1;v=fail[v]) 
                    ans+=val[v],val[v]=-1; //剪枝,跳过无需再跳
            }
            return ans;
        };
    }
    using namespace Trie;
    
    int main()
    {
        int n; scanf("%d",&n);
        for(int i=1;i<=n;++i) 
            scanf("%s",p),ins(p);
        build();	
        scanf("%s",str); 
        printf("%d",query(str));
        return 0;
    }
    
  • 相关阅读:
    基础编程练习题第一波
    TYVJ 1541 八数码
    NOIP 2014 寻找道路
    NOIP2014 解方程
    POJ 3213 矩阵乘法(优化)
    POJ 1523 Tarjan求割点
    POJ 3237 树链剖分+线段树
    SPOJ 375 树链剖分
    NOIP 2012 T2 国王游戏 (贪心+高精)
    POJ 1364 差分约束
  • 原文地址:https://www.cnblogs.com/list1/p/10382849.html
Copyright © 2011-2022 走看看