zoukankan      html  css  js  c++  java
  • hdu2222 ac自动机

    貌似字典树也能过,原理不多赘述了,主要就是字典树+kmp

    设匹配串长度为n,模式串共m个,第i个记为si。 
    时间复杂度为O(n+mi=1length(si))

    ac自动机大致就是用字典树存下每个分串,再处理出fail数组,最后根据母串和fail数组进行逐一匹配

    在对fail数组进行处理的时候,fail指向的是后缀相同且最长那一个节点

    (wa点:trie应该开全局变量,query时,以为是从root开始0到26进行向下匹配)

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define C 0.5772156649
    #define pi acos(-1.0)
    #define ll long long
    #define mod 1000000007
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    
    using namespace std;
    
    const double g=10.0,eps=1e-7;
    const int N=500000+10,maxn=60000+10,inf=0x3f3f3f;
    
    struct Trie{
        int Next[N][26],fail[N],cnt[N];
        int root,tot;
        int newnode()
        {
            for(int i=0;i<26;i++)
                Next[tot][i]=-1;
            cnt[tot]=0;
            return tot++;
        }
        void init()
        {
            tot=0;
            root=newnode();
        }
        void insertstring(string s)//插入字符串,构成字典树
        {
            int now=root;
            for(int i=0;i<s.size();i++)
            {
                if(Next[now][s[i]-'a']==-1)
                    Next[now][s[i]-'a']=newnode();
                now=Next[now][s[i]-'a'];
            }
            ++cnt[now];//每个字符串末尾++
        }
        void build()//构建fail数组,和next数组
        {
            queue<int>q;
            fail[root]=root;
            for(int i=0;i<26;i++)
            {
                if(Next[root][i]==-1)Next[root][i]=root;
                else
                {
                    fail[Next[root][i]]=root;
                    q.push(Next[root][i]);
                }
            }
            while(!q.empty())
            {
                int now=q.front();
                q.pop();
                for(int i=0;i<26;i++)
                {
                    if(Next[now][i]==-1)Next[now][i]=Next[fail[now]][i];
                    else
                    {
                        fail[Next[now][i]]=Next[fail[now]][i];
                        q.push(Next[now][i]);
                    }
                }
            }
        }
        int query(string s)
        {
            int now=root,res=0;
            for(int i=0;i<s.size();i++)
            {
             //   cout<<now<<" ";
                now=Next[now][s[i]-'a'];
                int temp=now;
                while(temp!=root)
                {
                   // cout<<temp<<" ";
                    res+=cnt[temp];
                    cnt[temp]=0;
                    temp=fail[temp];
                }
              //  cout<<endl;
            }
            return res;
        }
        void debug()
        {
            for(int i=0;i<tot;i++)
            {
                cout<<i<<" "<<fail[i]<<" "<<cnt[i]<<" ";
                for(int j=0;j<26;j++)
                    cout<<Next[i][j]<<" 
    "[i==25];
                cout<<endl;
            }
        }
    };
    Trie acm;
    string s;
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t,n;
        cin>>t;
        while(t--)
        {
            cin>>n;
            acm.init();
            for(int i=1;i<=n;i++)
            {
                cin>>s;
                acm.insertstring(s);
            }
            acm.build();
           // acm.debug();
            cin>>s;
            cout<<acm.query(s)<<endl;
        }
        return 0;
    }
    /********************
    1
    4
    abce
    abd
    cd
    bce
    abcde
    ********************/
    View Code
  • 相关阅读:
    《软件架构设计》温昱著读后感(一)
    质量属性II(信息领域热词分析)
    质量属性
    2020寒假学习进度报告16
    2020寒假学习进度报告15
    Nginx运行报错unknown directive ""
    使用ajax的几种方式
    Shiro中@RequiresAuthentication等等注解介绍
    shiro自定义异常无法被捕获总是抛出AuthenticationException解决方案
    java中String和int相互转换常用方法详解
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/7544799.html
Copyright © 2011-2022 走看看