zoukankan      html  css  js  c++  java
  • 【经典】ac自动机+矩阵快速幂——求长为n的不包含某些串的所有串个数 icpc cerc 2019

     老经典题了

    #include<bits/stdc++.h>
    using namespace std;
    #define N 105
    #define ll long long
    #define mod 1000000007
    
    ll n,m;
    char buf[N],s[N];
    
    struct Matrix{
        ll a[N][N];
        Matrix(){memset(a,0,sizeof a);}
    }A;
    
    struct Trie{
        int nxt[N][26],fail[N],end[N],L,root;
        int newnode(){
            memset(nxt[L],-1,sizeof nxt[L]);
            end[L]=0;
            return L++;
        }
        void init(){
            L=0;
            root=newnode();
        }
        void insert(char s[]){
            int len=strlen(s);
            int now=root;
            for(int i=0;i<len;i++){
                if(nxt[now][s[i]-'a']==-1)
                    nxt[now][s[i]-'a']=newnode();
                now=nxt[now][s[i]-'a'];
            }
            end[now]++;
        }
        void build(){
            queue<int>Q;
            fail[root]=root;
            for(int i=0;i<26;i++)
                if(nxt[root][i]==-1)
                    nxt[root][i]=root;
                else {
                    fail[nxt[root][i]]=root;
                    Q.push(nxt[root][i]);
                }
            while(!Q.empty()){
                int now=Q.front();Q.pop();
                if(end[fail[now]])end[now]=1;
                for(int i=0;i<26;i++){
                    if(nxt[now][i]==-1)
                        nxt[now][i]=nxt[fail[now]][i];
                    else {
                        fail[nxt[now][i]]=nxt[fail[now]][i];
                        Q.push(nxt[now][i]);
                    }
                }
            }
        }
        void buildMrx(){
            for(int i=0;i<L;i++)
                for(int j=0;j<26;j++)
                    if(!end[i] && !end[nxt[i][j]])
                        A.a[i][nxt[i][j]]++;
        }
    }ac;
    
    
    void Mul(Matrix &A,Matrix &B){
        Matrix res;
        for(int i=0;i<ac.L;i++)
            for(int j=0;j<ac.L;j++)
                for(int k=0;k<ac.L;k++)
                    res.a[i][j]=(res.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
        for(int i=0;i<ac.L;i++)
            for(int j=0;j<ac.L;j++)
                A.a[i][j]=res.a[i][j]; 
    }
    Matrix Matrix_Pow(Matrix A,ll b){
        Matrix res;
        for(int i=0;i<ac.L;i++)
            res.a[i][i]=1;
        while(b){
            if(b%2)Mul(res,A);
            b>>=1;Mul(A,A);
        }
        return res;
    }
    
    int main(){
        cin>>n>>m;
        ac.init();
        for(int i=1;i<=m;i++){
            int len;cin>>len>>buf;
            ac.insert(buf);
        }
        ac.build();
        ac.buildMrx();
        
        A=Matrix_Pow(A,n);
        
        ll ans=0;
        for(int i=0;i<ac.L;i++)
            ans=(ans+A.a[0][i])%mod;
        cout<<ans<<'
    '; 
    } 
  • 相关阅读:
    WHYZOJ-#53 线段树区间修改(线段树)
    洛谷-3373 【模板】线段树 2 (线段树)
    暑假训练-藏妹子之处(递推)
    POJ-1258 Agri-Net(kruskal最小生成树)
    POJ-2559 Largest Rectangle in a Histogram(单调栈)
    BZOJ3439 Kpm的MC密码
    BZOJ3438 小M的作物
    BZOJ3436 小K的农场
    BZOJ3437 小P的牧场
    BZOJ1430 小猴打架
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12904662.html
Copyright © 2011-2022 走看看