zoukankan      html  css  js  c++  java
  • 【CF696D】 Legen...

    Legen...

    题意

    翻译版本:

    Solution

    首先肯定是AC机上面的DP了

    状转的柿子是显然的:(dp[k][i]=max(dp[k][i],dp[k-1][j]+val[i][j])),其中i和j都是AC自动机里面的节点,(val[i][j])表示从i节点到j节点可以增加的贡献

    然后可以考虑一下用类似于矩阵乘法的方式转移:

    一个矩阵(A),其中i行j列表示一开始从i节点转移来,然后转移到j节点的最大答案

    然后每次转移就是(now_A[i][j]=max(now_A[i][j],last_A[i][k]+val[k][j]))

    然后就可以用类似于矩阵快速幂的方法转移了

    总共的时间复杂度是(O(log_n(m imes l) ^ 3))

    l是平均长度,m字符串是个数

    因为(m imes l)最大只有200,所以可以通过这个题

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int tot;
    struct node{
        int a[210][210];
        node(){memset(a,-0x3f,sizeof(a));}
        node operator * (node b){
            node ret;
            for(int i=0;i<=tot;++i){
                for(int j=0;j<=tot;++j){
                    for(int k=0;k<=tot;++k){
                        ret.a[i][j]=max(ret.a[i][j],a[i][k]+b.a[k][j]);
                    }
                }
            }
            return ret;
        }
    };
    node fastpow(node a,int k){
        node ret;
        for(int i=0;i<=tot;++i){
            ret.a[i][i]=0;
        }
        while(k){
            if(k&1)ret=ret*a;
            a=a*a;
            k>>=1;
        }
        return ret;
    }
    int ch[210][26];
    int val[6010];
    char s[210];
    int rt;
    void insert(int w){
        int len=strlen(s+1);
        int now=rt;
        for(int i=1;i<=len;++i){
            int son=s[i]-'a';
            if(!ch[now][son]){
                ch[now][son]=++tot;
            }
            now=ch[now][son];
        }
        val[now]+=w;
    }
    int fail[6010];
    void getfail(){
        queue<int> q;
        for(int i=0;i<26;++i){
            if(ch[rt][i])q.push(ch[rt][i]);
        }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            val[u]+=val[fail[u]];
            for(int i=0;i<26;++i){
                if(ch[u][i]){
                    fail[ch[u][i]]=ch[fail[u]][i];
                    q.push(ch[u][i]);
                }
                else ch[u][i]=ch[fail[u]][i];
            }
        }
    }
    node start;
    void init(){
        for(int i=0;i<=tot;++i){
            for(int j=0;j<26;++j){
                int x=ch[i][j];
                start.a[i][x]=val[x];
            }
        }
    }
    int aaaa[210];
    signed main(){
        int n,m;
        scanf("%I64d%I64d",&m,&n);
        for(int i=1;i<=m;++i){
            scanf("%I64d",&aaaa[i]);
        }
        for(int i=1;i<=m;++i){
            memset(s,0,sizeof(s));
            scanf("%s",s+1);
            insert(aaaa[i]);
        }
        getfail();
        init();
        start=fastpow(start,n);
        int final=0;
        for(int i=1;i<=tot;++i){
            final=max(final,start.a[0][i]);
        }
        printf("%I64d
    ",final);
    }
    

    (是CF题只好I64d了)

  • 相关阅读:
    【转】c++ http下载文件
    unity事件
    【Unity3D自学记录】判断物体是否在镜头内
    Unity3D研究院之获取摄像机的视口区域
    Unity3D特效-场景淡入淡出
    Unity3D深入浅出
    胶囊碰撞体(CapsuleCollider)
    unity Dotween插件的简单介绍及示例代码
    使用Animation实现摄像机动画
    Unity3D研究院之使用Animation编辑器编辑动画
  • 原文地址:https://www.cnblogs.com/youddjxd/p/11772189.html
Copyright © 2011-2022 走看看