[Codeforces 696D] Legen...
题目大意:
给出一些匹配串,要造一个长度不超过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...的更多相关文章
- Codeforces 696D Legen...(AC自动机 + 矩阵快速幂)
题目大概说给几个字符串,每个字符串都有一个开心值,一个串如果包含一次这些字符串就加上对应的开心值,问长度n的串开心值最多可以是多少. POJ2778..复习下..太弱了都快不会做了.. 这个矩阵的乘法 ...
- 【Codeforces 696D】Legen...
Codeforces 696 D 题意:给\(n\)个串,每个串有一个权值\(a_i\),现在要构造一个长度为\(l\leq 10^{14}\)的串,如果其中包含了第\(i\)个串,则会得到\(a_i ...
- CodeForces - 697F:Legen... (AC自动机+矩阵)
Barney was hanging out with Nora for a while and now he thinks he may have feelings for her. Barney ...
- Codeforces 696 D. Legen...
Description 每个字符串有些价值,问生成长度为 \(l\) 的字符串最多能获得多少价值,总字符数不超过 \(200\), \(l\leqslant 10^{14}\) . Sol AC自动机 ...
- Codeforces Round #362(Div1) D Legen...(AC自动机+矩阵快速幂)
题目大意: 给定一些开心串,每个串有一个开心值,构造一个串,每包含一次开心串就会获得一个开心值,求最大获得多少开心值. 题解: 首先先建立AC自动机.(建立fail指针的时候,对val要进行累加) 然 ...
- codeforces泛做..
前面说点什么.. 为了完成日常积累,傻逼呵呵的我决定来一发codeforces 挑水题 泛做.. 嗯对,就是泛做.. 主要就是把codeforces Div.1的ABCD都尝试一下吧0.0.. 挖坑0 ...
- python爬虫学习(5) —— 扒一下codeforces题面
上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...
- 【Codeforces 738D】Sea Battle(贪心)
http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...
- 【Codeforces 738C】Road to Cinema
http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...
随机推荐
- jQuery对表单元素的取值和赋值操作代码(转)
使用常规的思路:$("#keyword").value 取值是取不到的,因为此时$('#keydord')已经不是个element,而是个jquery对象,所以应该使用:$(&qu ...
- mongodb 复制集
mongodb 复制集 复制集简介 Mongodb复制集由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写 ...
- 解决vue.js修改数据无法触发视图
data:{checkValue:{}}that.checkValue[key] = [] 赋值无法实时改变变量:(数据其实最终被修改,但是并没有触发检测从而更新视图)原因:Vue 不能检测到对象属性 ...
- ABAP中的枚举对象
枚举对象是枚举类型的数据对象.枚举对象只能包含类型为枚举类型的枚举值.ABAP从版本7.51开始支持它们. 这是一种常见的模式.在ABAP 7.51之前,人们通常用如下方式实现类似的功能: CLASS ...
- bzoj 2109: [Noi2010]Plane 航空管制
Description 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频 发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此, 小X表示很不满意. 在这次来烟台的 ...
- fdisk 命令详解
fdisk 作用: 查看磁盘实体使用情况,也可对硬盘分区. 选项: -b 分区大小 -l 列出指定的外围设备的分区表状况 -s 分区编号, 将指定的分区大小输出到标准输出上, 单位为区块 -u ...
- Python 项目实践三(Web应用程序)第三篇
接着上节的继续学习,现在要显示所有主题的页面 有了高效的网页创建方法,就能专注于另外两个网页了:显示全部主题的网页以及显示特定主题中条目的网页.所有主题页面显示用户创建的所有主题,它是第一个需要使用数 ...
- 手动编译protobuf3的C++源码
Windows下编译 官方文档 第三方文档 准备工具 Visual Studio 2013 CMake https://cmake.org/ Git https://git-scm.com/ 需要注意 ...
- File API文件操作之FileReader二
上一篇说了FileAPI中FileReader的readAsText,这里继续上文,说说另外一个API readAsDataURL. 这个接口是将File或者Blob读成base64格式的字符串,然后 ...
- jQuery 入门
不能正常引用jQuery-2.2.4.min.js所以代码没生效 jQuery 是一个 JavaScript 函数库.jQuery 库包含以下特性: HTML 元素选取 HTML 元素操作 CSS 操 ...