题目大意:

    给出一些匹配串,要造一个长度不超过L的字符串,每个匹配串有自己的价值,匹配串每次出现在字符串里都会贡献一次价值...要求可能得到的最大价值。

    匹配串总长不超200,L<=10^14,时限6s

  典型的倍增floyd...看数据范围大概就知道是什么东西了= =

  暴力写法的话..建个AC自动机,每个节点的价值,就是结束节点在它的fail链上的匹配串的价值总和。。 然后在上面暴力DP。f[i][j]表示从i节点开始,往后走j步能得到的最大价值。

  这个形式和USACO那道“奶牛接力跑‘一模一样。。。

  f[i][j][k]表示从i节点开始,走2^j步,到达k的最大价值。fa[i][j][k]:从k节点开始,走2^j步,能否到达i。

  f[i][j][k]=max{ f[i][j-1][k1]+f[k1][j-1][k] },( fa[k1][j-1][i]和fa[k][j-1][k1]为true

  求出f后,就和快速幂的姿势一样把L拆成若干个二的次幂之和,然后把对应的各个f数组并起来(记为g)。

  最后的答案就是max{ g[0][i] },(i为自动机上的节点。

  时间复杂度O(n^3*logL)..CF测评姬挺快的。。只跑了1200+ms。。

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<bitset>
#define ll long long
#define ull unsigned long long
#define d double
using namespace std;
const int maxn=;
const ll inf=(1ll<<)-1ll;
int ch[maxn][],next[maxn][],tot;
int dl[maxn],fail[maxn],val[maxn],v[maxn];
ll f[maxn][][maxn],g[maxn][][maxn];
bitset<maxn>fa[maxn][];
char s[maxn]; int i,j,k,n,m,now,pre;
ll L;
bool first=; int ra,fh;char rx;
inline int read(){
rx=getchar(),ra=,fh=;
while(rx!='-'&&(rx<''||rx>''))rx=getchar();
if(rx=='-')fh=-,rx=getchar();
while(rx>=''&&rx<='')ra*=,ra+=rx-,rx=getchar();return ra*fh;
}
inline void upd(ll &a,ll b){if(a<b)a=b;} void trie(int n,int v){
int p=;
for(int i=;i<=n;i++){
s[i]-='a';
if(!ch[p][s[i]])ch[p][s[i]]=++tot,p=tot;
else p=ch[p][s[i]];
}
val[p]+=v;//printf(" ggpos:%d\n",p);
}
void getfail(){
int l=,r=,i,now,j,p;dl[]=;
while(l<r){
now=dl[++l];
for(i=;i<;i++)if(ch[now][i]){
j=ch[now][i],dl[++r]=j,next[now][i]=j;
for(p=fail[now];p&&!ch[p][i];p=fail[p]);
if(!now)fail[j]=;else fail[j]=ch[p][i];
val[j]+=val[fail[j]];//printf(" %d - - - ->%d val:%d\n",j,fail[j],val[j]);
}else{
for(p=fail[now];p&&!ch[p][i];p=fail[p]);
next[now][i]=ch[p][i];
}
}
} inline void run_fa(int j){
int i,k1;//printf("j:%d\n",j);
for(i=;i<=tot;i++)for(k1=;k1<=tot;k1++)
if(fa[i][j-][k1])fa[i][j]|=fa[k1][j-];
// for(i=0;i<=tot;i++)for(k1=0;k1<=tot;k1++)if(fa[i][j][k1])printf(" %d->%d\n",k1,i);
}
inline void run_f(int j){
int i,k;register int k1;//printf("j:%d\n",j);
for(i=;i<=tot;i++)for(k=;k<=tot;k++)if(fa[k][j][i]){
for(k1=;k1<=tot;k1++)if(fa[k1][j-][i]&&fa[k][j-][k1])
upd(f[i][j][k],f[i][j-][k1]+f[k1][j-][k]);//,printf(" %d-->%d-->%d\n",i,k1,k);
}else f[i][j][k]=-inf;
}
inline void run_merge(int j){
int i,k;register int k1;
if(first){
first=;
for(i=;i<=tot;i++)for(k=;k<=tot;k++)g[i][now][k]=f[i][j-][k];
return;
}
for(i=;i<=tot;i++)for(k=;k<=tot;k++)
for(g[i][now][k]=-inf,k1=;k1<=tot;k1++)if(fa[k][j-][k1])
upd(g[i][now][k],g[i][pre][k1]+f[k1][j-][k]);
} int main(){
n=read(),scanf("%I64d",&L);
for(i=;i<=n;i++)v[i]=read();
for(i=;i<=n;i++)scanf("%s",s+),trie(strlen(s+),v[i]);
getfail(); int a=;
for(i=;i<=tot;i++)for(k=;k<=tot;k++)f[i][][k]=-inf;
for(i=;i<=tot;i++)for(j=;j<;j++)fa[next[i][j]][][i]=,f[i][][next[i][j]]=val[next[i][j]]; // for(i=0;i<=tot;i++)for(int k1=0;k1<=tot;k1++)if(fa[i][0][k1])printf(" %d->%d\n",k1,i); now=,pre=;
while(L){
a++;
if(L&)run_merge(a),swap(now,pre);
L>>=;
if(!L)break;
run_fa(a),run_f(a);
}
ll ans=;
for(i=;i<=tot;i++)upd(ans,g[][pre][i]);
printf("%I64d\n",ans);
}

比赛的时候这道题肝了整整1h。。。最后1min才过的样例..竟然就过掉了

最新文章

  1. android 实现返回键执行home键方法
  2. SSIS 数据源组件的External Metadata和Advanced Property
  3. 文本提交带单引号引起mysql报错
  4. DUT Star Round2
  5. Enable SSHD on Ubuntu
  6. LeetCode(一)
  7. int与string的相互转换
  8. struts2.1.6教程十一、注解配置
  9. 运行shell脚本时报错&quot;[[ : not found&quot;解决方法
  10. Wincc flexable的按钮组态
  11. hdu_1026(最短路)
  12. Several ports (8005, 8080, 8009)被占用
  13. kafka的安装以及基本用法
  14. controller分支实现前台显示弹框同时转发
  15. 13. nginx,lvs之一
  16. jQuery获取地址栏中的链接参数
  17. CSS魔法堂:稍稍深入伪类选择器
  18. js 事件模型
  19. 【论文学习】YOLO9000: Better,Faster,Stronger(YOLO9000:更好,更快,更强)
  20. 20155208徐子涵 2016-2017-2 《Java程序设计》第8周学习总结

热门文章

  1. Node之Express服务器启动安装与配置
  2. 小白的 MySQL 笔记(一)
  3. bzoj 3991: [SDOI2015]寻宝游戏
  4. SQL Server中varchar和nvarchar的区别
  5. IT服务(运维)管理实施的几个要点--第二章 人员和组织架构
  6. MySQL5.6中date和string的转换和比较
  7. python3 python2 import 的区别
  8. jquery学习总结(超级详细)
  9. 一种优雅的条件引用第三方.net库的方法
  10. HTML学习 表格和表单