CF696D場所...

カート...

問題の意味

翻訳:

解決

もちろん、DP上記ACユニットであります

形状ターン柿は明らかである:\(DP [K] [I] = MAX(DP [K] [I]、DP [K-1] [J] +ヴァル[I] [J])\)、前記iおよびj ACオートマトン内部ノードである\(ヴァル[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の\ \ 3)\ ^回L))

Lは、mは列の数平均長さであります

以降\(Mの\回数L \)のみ200の最大ので、この問題があることができます

コード:

#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\n",final);
}

(CFはI64dた質問です)

おすすめ

転載: www.cnblogs.com/youddjxd/p/11772189.html