• Codeforces 696D Legen...(AC自动机 + 矩阵快速幂)


    题目大概说给几个字符串,每个字符串都有一个开心值,一个串如果包含一次这些字符串就加上对应的开心值,问长度n的串开心值最多可以是多少。

    POJ2778。。复习下。。太弱了都快不会做了。。

    这个矩阵的乘法定义是不同的,m[i][j]=max(m1[i][k]+m2[k][j]),即从i走到k能获得的最大值与从k走到j能获得的最大值之和去更新从i到j能获得的最大值。

    另外。。关于矩阵内的初始值。。用-1表示从i不能到j,比如初始的时候,i不能走一步到j结点这时值就应该设置成-1;而不能用0,因为0是有意义的,它表示能走但不能获得价值。。这个搞了好久。。好累。。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 
     8 int tn,ch[222][26],fail[222],sum[222];
     9 void insert(char *s,int a){
    10     int x=0;
    11     for(int i=0; s[i]; ++i){
    12         int y=s[i]-'a';
    13         if(ch[x][y]==0) ch[x][y]=++tn;
    14         x=ch[x][y];
    15     }
    16     sum[x]+=a;
    17 }
    18 void getfail(){
    19     queue<int> que;
    20     for(int i=0; i<26; ++i){
    21         if(ch[0][i]) que.push(ch[0][i]);
    22     }
    23     while(!que.empty()){
    24         int x=que.front(); que.pop();
    25         for(int y=0; y<26; ++y){
    26             if(ch[x][y]) que.push(ch[x][y]),fail[ch[x][y]]=ch[fail[x]][y],sum[ch[x][y]]+=sum[ch[fail[x]][y]];
    27             else ch[x][y]=ch[fail[x]][y];
    28         }
    29     }
    30 }
    31 
    32 int val[222];
    33 char str[222];
    34 
    35 struct Mat{
    36     long long m[222][222];
    37     Mat(){
    38         memset(m,-1,sizeof(m));
    39     }
    40 };
    41 Mat operator*(const Mat &m1,const Mat &m2){
    42     Mat m;
    43     for(int i=0; i<=tn; ++i){
    44         for(int j=0; j<=tn; ++j){
    45             for(int k=0; k<=tn; ++k){
    46                 if(m1.m[i][k]==-1 || m2.m[k][j]==-1) continue;
    47                 m.m[i][j]=max(m.m[i][j],m1.m[i][k]+m2.m[k][j]);
    48             }
    49         }
    50     }
    51     return m;
    52 }
    53 
    54 int main(){
    55     int n; long long l;
    56     scanf("%d%lld",&n,&l);
    57     for(int i=1; i<=n; ++i) scanf("%d",val+i);
    58     for(int i=1; i<=n; ++i){
    59         scanf("%s",str);
    60         insert(str,val[i]);
    61     }
    62 
    63     getfail();
    64 
    65     Mat m;
    66     for(int i=0; i<=tn; ++i){
    67         for(int j=0; j<26; ++j){
    68             m.m[i][ch[i][j]]=sum[ch[i][j]];
    69         }
    70     }
    71 
    72     Mat res=m;
    73     --l;
    74     while(l){
    75         if(l&1){
    76             res=res*m;
    77         }
    78         m=m*m;
    79         l>>=1;
    80     }
    81 
    82     long long ans=0;
    83     for(int i=0; i<=tn; ++i){
    84         ans=max(ans,res.m[0][i]);
    85     }
    86     printf("%lld",ans);
    87     return 0;
    88 }
  • 相关阅读:
    简单图片预加载
    前端进行图片压缩
    原生js实现拖动滑块验证
    chrome和IE下的滚动条样式修改
    简单canvas刮刮乐
    时间轴
    简单边框动画
    滚动指示器
    美化checkbox多选框
    将过长的文字改用省略号显示
  • 原文地址:https://www.cnblogs.com/WABoss/p/5727592.html
Copyright © 2020-2023  润新知