CodeForces 696D Legen…
原题地址:http://codeforces.com/problemset/problem/696/D
题意:
Barney爱上了Nora 想发给她一段长为
l
的话(一个由小写字母组成的串)让她开心一下。
Nora有n个喜欢的话(例如 I’m falling for you 这种情话。当然,给出的都是由小写字母组成的串),每个串
给出这些串和它们的开心值,求出长为 l 的串能达到的最大开心值。
数据范围
题解:
补全AC自动机得到一个邻接矩阵,然后跑矩阵快速幂。
当然,要注意哪些不能转移,
与求方案数不同的是,转移不是乘积之和,而是和的最大值。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define LL long long
using namespace std;
const int N=205;
LL L;
queue<int> Q;
int n,a[N],ch[N][26],val[N],root=0,tail=0,fail[N];
char str[N];
struct Matrix
{
LL M[N][N];
Matrix(){memset(M,-1,sizeof(M));}
inline friend Matrix operator*(const Matrix &A,const Matrix &B)
{
Matrix C;
for(int i=0;i<=tail;i++)
for(int j=0;j<=tail;j++)
for(int k=0;k<=tail;k++)
if(A.M[i][k]>=0&&B.M[k][j]>=0) C.M[i][j]=max(C.M[i][j],A.M[i][k]+B.M[k][j]);
return C;
}
};
void insert(int id)
{
int len=strlen(str); int tmp=root;
for(int i=0;i<len;i++)
{
int c=str[i]-'a';
if(!ch[tmp][c]) ch[tmp][c]=++tail;
tmp=ch[tmp][c];
}
val[tmp]+=a[id];
}
void getfail()
{
for(int i=0;i<26;i++) if(ch[root][i]) Q.push(ch[root][i]),fail[ch[root][i]]=root; else ch[root][i]=root;
while(!Q.empty())
{
int top=Q.front(); Q.pop();
for(int i=0;i<26;i++)
{
if(!ch[top][i]) ch[top][i]=ch[fail[top]][i];
else
{
int u=ch[top][i];
fail[u]=ch[fail[top]][i];
val[u]+=val[fail[u]];
Q.push(u);
}
}
}
}
int main()
{
scanf("%d",&n); scanf("%I64d",&L);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%s",str),insert(i);
getfail();
Matrix ret,base;
for(int i=0;i<=tail;i++)
for(int c=0;c<26;c++)
{
int j=ch[i][c];
ret.M[i][j]=val[j];
}
base=ret; L--;
for(;L;L>>=1)
{
if(L&1) ret=ret*base;
base=base*base;
}
LL ans=0;
for(int i=0;i<=tail;i++) ans=max(ans,ret.M[0][i]);
printf("%I64d\n",ans);
return 0;
}
这一套题的小表情太可爱了