• poj2778 ac自动机+矩阵快速幂


    给m个子串,求长度为n的不包含子串的母串数,最直接的应该是暴搜,肯定tle,考虑用ac自动机

    将子串建成字典树,通过next表来构造矩阵,然后用矩阵快速幂求长度为n的数量

    邻接矩阵https://wenku.baidu.com/view/d7b9787f1711cc7931b716b0.html

    对于a(i,j)^k  是指从i到j经过k个点的所有情况数

    注意对于End数组,如果某个节点如果fail指针End数组为1,那么End【该节点】也是1

    string要开全局变量,不然不能运行= =

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<iomanip>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #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 100000
    #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=100+10,maxn=100+10,inf=0x3f3f3f;
    
    struct Node{
        int len;
        ll a[N][N];
    };
    Node mul(Node x,Node y)
    {
        Node ans;
        ans.len=x.len;
        memset(ans.a,0,sizeof ans.a);
        for(int i=0;i<x.len;i++)
            for(int j=0;j<x.len;j++)
                for(int k=0;k<y.len;k++)
                    ans.a[i][k]=(ans.a[i][k]+x.a[i][j]*y.a[j][k])%mod;
        return ans;
    }
    Node quick_mul(Node x,int n)
    {
        Node ans;
        ans.len=x.len;
        memset(ans.a,0,sizeof ans.a);
        for(int i=0;i<ans.len;i++)ans.a[i][i]=1;
        while(n)
        {
            if(n&1)ans=mul(ans,x);
            x=mul(x,x);
            n/=2;
        }
        return ans;
    }
    struct Trie{
        int tot,root;
        int Next[N][4],fail[N];
        bool End[N];
        int change(char s)
        {
            if(s=='A')return 0;
            else if(s=='C')return 1;
            else if(s=='T')return 2;
            else return 3;
        }
        int newnode()
        {
            for(int i=0;i<4;i++)
                Next[tot][i]=-1;
            End[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][change(s[i])]==-1)
                    Next[now][change(s[i])]=newnode();
                now=Next[now][change(s[i])];
            }
            End[now]=1;
        }
        void build()
        {
            queue<int>q;
            fail[root]=root;
            for(int i=0;i<4;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();
                if(End[fail[now]])End[now]=1;
                for(int i=0;i<4;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 solve(int n)
        {
            Node ans;
            ans.len=tot;
            memset(ans.a,0,sizeof ans.a);
            for(int i=0;i<tot;i++)
                for(int j=0;j<4;j++)
                    if(!End[Next[i][j]])
                        ans.a[i][Next[i][j]]++;
            ans=quick_mul(ans,n);
            int res=0;
            for(int i=0;i<ans.len;i++)
                res=(res+(int)ans.a[0][i])%mod;
            return res;
        }
    };
    Trie ac;
    string s;
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,m;
        while(cin>>m>>n)
        {
            ac.init();
            for(int i=0;i<m;i++)
            {
                cin>>s;
                ac.insertstring(s);
            }
            ac.build();
            cout<<ac.solve(n)<<endl;
        }
        return 0;
    }
    /********************
    
    ********************/
    View Code
  • 相关阅读:
    vs2017中信号与槽连接
    生成格雷码
    结构光三维测量技术
    格雷码生成算法
    结构光三维重建
    Qt之CMake和MinGW编译OpenCV
    qt+opencv编译环境的配置
    vs2017+opencv配置参考链接
    2019-3-25多线程的同步与互斥(互斥锁、条件变量、读写锁、自旋锁、信号量)
    2019-3-22c# TextBox只允许输入数字,禁用右键粘贴,允许Ctrl+v粘贴数字
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/7569318.html
Copyright © 2020-2023  润新知