题目大意:

    给出一些匹配串,要造一个长度不超过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才过的样例..竟然就过掉了

[Codeforces 696D] Legen...的更多相关文章

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

    题目大概说给几个字符串,每个字符串都有一个开心值,一个串如果包含一次这些字符串就加上对应的开心值,问长度n的串开心值最多可以是多少. POJ2778..复习下..太弱了都快不会做了.. 这个矩阵的乘法 ...

  2. 【Codeforces 696D】Legen...

    Codeforces 696 D 题意:给\(n\)个串,每个串有一个权值\(a_i\),现在要构造一个长度为\(l\leq 10^{14}\)的串,如果其中包含了第\(i\)个串,则会得到\(a_i ...

  3. CodeForces - 697F:Legen... (AC自动机+矩阵)

    Barney was hanging out with Nora for a while and now he thinks he may have feelings for her. Barney ...

  4. Codeforces 696 D. Legen...

    Description 每个字符串有些价值,问生成长度为 \(l\) 的字符串最多能获得多少价值,总字符数不超过 \(200\), \(l\leqslant 10^{14}\) . Sol AC自动机 ...

  5. Codeforces Round #362(Div1) D Legen...(AC自动机+矩阵快速幂)

    题目大意: 给定一些开心串,每个串有一个开心值,构造一个串,每包含一次开心串就会获得一个开心值,求最大获得多少开心值. 题解: 首先先建立AC自动机.(建立fail指针的时候,对val要进行累加) 然 ...

  6. codeforces泛做..

    前面说点什么.. 为了完成日常积累,傻逼呵呵的我决定来一发codeforces 挑水题 泛做.. 嗯对,就是泛做.. 主要就是把codeforces Div.1的ABCD都尝试一下吧0.0.. 挖坑0 ...

  7. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  8. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  9. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

随机推荐

  1. 插值查找C++

    和上一篇折半查找很类似,只有四则运算不一样,思想类似. 只是在插值查找的过程中,考虑了查找键的值. #include <iostream> using namespace std; //需 ...

  2. Thinkphp开启调试模式

    3.0版本的调试模式开启,必须在项目入口文件中添加常量APP_DEBUG定义,如下: define('APP_DEBUG',True); // 开启调试模式 开启调试模式后,你可能感觉不到什么变化,不 ...

  3. rtmp流媒体搭建的所需安装包

    说明:这是基于nginx rtmp控件  搭建的rtmp流媒体服务器,在此附上的是搭建所需要的安装包,具体的搭建过程看我之前的"ubuntu流媒体搭建" 链接地址:http://p ...

  4. LAMP第二部分apache配置

    课程大纲:1. 下载discuz! mkdir /data/wwwcd /data/wwwwget  http://download.comsenz.com/DiscuzX/3.2/Discuz_X3 ...

  5. ActiveMQ (一) 初识ActiveMQ

    了解JMS JMS即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进 ...

  6. Augustus安装小记

    之前安装过一次Augustus,由于节点重新部署后,原来安装的硬盘被格掉了,今天重新安装的时候出了一些问题,记录一下. 1. 需要boost,安装好boost之后,虽然将其加入到~/.bashrc配置 ...

  7. vue:简单方法替代vuex或者bus

    兄弟组件,隔代组件传值很麻烦,方法虽然多,但都各有缺点. vuex: 适合数据量大,并且函数集中处理. bus:适合数据虽少,却不得不用的时候,维护困难. root:这儿指将值挂在root组件上,需要 ...

  8. Micropython实例之TPYBoard来电显示功能演示

    一.TPYBoardV702介绍 TPYBoardV702是目前市面上唯一支持通信通信功能的MicroPython开发板:支持Python3.0及以上版本直接运行.支持GPS+北斗双模通信.GPRS通 ...

  9. HTML5 Audio/Video 标签,属性,方法,事件汇总 (转)

    HTML5 Audio/Video 标签,属性,方法,事件   <audio> 标签属性:src:音乐的URLpreload:预加载autoplay:自动播放loop:循环播放contro ...

  10. Docker三十分钟快速入门(上)

    一.背景 ​ 最近,Docker技术真是一片火热,它的出现也弥补了虚拟机资源消耗过高的问题,直接让虚拟化技术有了质的飞跃.那么本文我们来聊一聊Docker,和大家一起认识Docker,简单入门Dock ...