题意:n个字符串(价值val[i]),请构造长度为l的字符串,使它的价值最大(子串的价值之和)。
题解:
配合 POJ 2778食用。
http://blog.csdn.net/qq_32707623/article/details/54574281
这题要搞清楚End数组的含义(以该节点结束的字符串的价值)。
还要注意矩阵的模型(两状态如果不可达,mat[i][j]=-inf)。
注意单位矩阵的值。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int N=205;
const ll inf=1e18;
int m;
struct Tire {
int Next[N][30],fail[N],End[N];
int root,tot;
int newNode() {
memset(Next[tot],-1,sizeof(Next[tot]));
End[tot]=0;
return tot++;
}
void init() {
tot=0;
root=newNode();
}
void insert(char *buf,int x) {
int len=strlen(buf);
int now=root;
for(int i=0;i<len;++i) {
if(Next[now][buf[i]-'a']==-1) {
Next[now][buf[i]-'a']=newNode();
}
now=Next[now][buf[i]-'a'];
}
End[now]+=x;
}
void build() {
queue<int> q;
fail[root]=root;
for(int i=0;i<26;++i) {
if(Next[root][i]==-1) {
Next[root][i]=root;
} else {
fail[Next[root][i]]=root;
q.push(Next[root][i]);
}
}
while(!q.empty()) {
int now=q.front();q.pop();
for(int i=0;i<26;++i) {
if(Next[now][i]==-1) {
Next[now][i]=Next[fail[now]][i];
} else {
fail[Next[now][i]]=Next[fail[now]][i];
End[Next[now][i]]+=End[Next[fail[now]][i]];
q.push(Next[now][i]);
}
}
}
}
}ac;
struct Mat {
ll mat[N][N];
Mat() {
for(int i=0;i<m;++i) {
for(int j=0;j<m;++j) {
mat[i][j]=-inf;
}
}
}
Mat operator * (Mat B) {
Mat C;
for(int i=0;i<m;++i) {
for(int j=0;j<m;++j) {
for(int k=0;k<m;++k) {
C.mat[i][j]=max(C.mat[i][j],mat[i][k]+B.mat[k][j]);
}
}
}
return C;
}
};
Mat powmul(Mat A,ll k) {
Mat B;
for(int i=0;i<m;++i) B.mat[i][i]=0;
while(k) {
if(k&1) B=B*A;
A=A*A;
k>>=1;
}
return B;
}
int val[N];
char s[N];
int main() {
int n;ll L;
while(~scanf("%d%I64d",&n,&L)) {
ac.init();
for(int i=1;i<=n;++i) scanf("%d",&val[i]);
for(int i=1;i<=n;++i) {
scanf("%s",s);
ac.insert(s,val[i]);
}
ac.build();
m=ac.tot;Mat M;
for(int i=0;i<m;++i) {
for(int k=0;k<26;++k) {
int j=ac.Next[i][k];
M.mat[i][j]=ac.End[j];
}
}
Mat Ans=powmul(M,L);
ll ans=0;
for(int i=0;i<m;++i) ans=max(ans,Ans.mat[0][i]);
printf("%I64d\n",ans);
}
return 0;
}