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 }
原文地址:https://www.cnblogs.com/WABoss/p/5727592.html