题目

描述

题目大意

给你一堆小串,每个小串都有一定的分数。

让你构造一个字符串,若子串中出现了之前的小串,就可以得到对应的分数(可以重复)

问最大分数。


思考历程

一看这题就知道是什么字符串方面的算法。

然后就很自然地想到AC自动机,多串匹配嘛!

接下来就想到建字符串的过程中,一个指针在AC自动机上跳来跳去……

先建出AC自动机,然后算出到达每个节点的贡献。

对于每个节点,枚举字母,若没有出边,就想着用failfailfail往上跳,然后将出边连向那个地方。

从此AC自动机变成了一张有向图,每个点都有262626条出边。题目就转成了在这张有向图上,走mmm步所的最大点权和。

感觉转化到这一步之后就想不出什么了,考虑过最长路一类的做法,都是没有成功。

于是我也不追求满分了,直接跑DP水分。


正解

事实上……

题目中有这么一句话:字符串的长度和不超过200200200。

知道这一切之后我疯了。

既然这样,那不就是一个裸的矩阵乘法吗?

时间就是2003lg⁡m200^3\lg m2003lgm,在6000ms中肯定是可以过的。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
int n;
long long m;
int a[210];
char str[210];
struct Node{
int c[26],fail;
int v;
} d[210];
int cnt,root;
inline void insert(char *s,int val){
int t=root;
for (;*s;++s){
if (!d[t].c[*s-'a'])
d[t].c[*s-'a']=++cnt;
t=d[t].c[*s-'a'];
}
d[t].v+=val;
}
inline void build(){//求fail,顺便做了对空儿子的处理。显然这两步是可以放在一起的
static int q[210];
int head=0,tail=1;
d[root].fail=root;
q[1]=root;
do{
int t=q[++head];
for (int i=0;i<26;++i){
if (d[t].c[i])
q[++tail]=d[t].c[i];
if (t==root){
if (d[t].c[i])
d[d[t].c[i]].fail=root;
else
d[t].c[i]=root;
continue;
}
int nxt=d[t].fail;
while (nxt!=root && !d[nxt].c[i])
nxt=d[nxt].fail;
if (d[nxt].c[i]){
if (d[t].c[i]){
d[d[t].c[i]].fail=d[nxt].c[i];
d[d[t].c[i]].v+=d[d[nxt].c[i]].v;
}
else
d[t].c[i]=d[nxt].c[i];
}
else{
if (d[t].c[i])
d[d[t].c[i]].fail=root;
else
d[t].c[i]=root;
}
}
}
while (head!=tail);
}
struct Matrix{
long long mat[210][210];
inline void operator*=(Matrix &b){
static Matrix res;
memset(res.mat,200,sizeof res);
for (int i=1;i<=cnt;++i)
for (int j=1;j<=cnt;++j)
for (int k=1;k<=cnt;++k)
res.mat[i][j]=max(res.mat[i][j],mat[i][k]+b.mat[k][j]);
memcpy(mat,res.mat,sizeof mat);
}
} f;
inline void get_pow(Matrix &x,long long m){
static Matrix res;
memset(res.mat,200,sizeof res);
for (int i=1;i<=cnt;++i)
res.mat[i][i]=0;
for (;m;m>>=1,x*=x)
if (m&1)
res*=x;
memcpy(x.mat,res.mat,sizeof x);
}
int main(){
cnt=root=1;
scanf("%d%lld",&n,&m);
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
for (int i=1;i<=n;++i){
scanf("%s",str);
insert(str,a[i]);
}
build();
memset(f.mat,200,sizeof f);
for (int i=1;i<=cnt;++i)
for (int j=0;j<26;++j)
f.mat[i][d[i].c[j]]=d[d[i].c[j]].v;
get_pow(f,m);
long long ans=0;
for (int i=1;i<=cnt;++i)
ans=max(ans,f.mat[1][i]);
printf("%lld\n",ans);
return 0;
}

总结

不想说什么……

如果不是没有看到,我这题早就AC的……

[JZOJ4649] 【NOIP2016提高A组模拟7.17】项链的更多相关文章

  1. 【JZOJ4787】【NOIP2016提高A组模拟9.17】数格子

    题目描述 输入 输出 样例输入 1 10000 3 10000 5 10000 0 0 样例输出 1 11 95 数据范围 每个测试点数据组数不超过10组 解法 状态压缩动态规划. 设f[i][j]表 ...

  2. 【NOIP2016提高A组模拟9.17】序列

    题目 分析 首先用\(a_i\)表示达到目标的步数\(B_i-A_i(mod 4)\) 根据粉刷栅栏,先不管mod 4的情况,答案就是\(\sum\max(a_i-a_{i+1},0)\) 那我们刚才 ...

  3. NOIP2016提高A组模拟9.17总结

    第一题,典型的隔板问题, 但是我忘记隔板问题怎么打,一开始在花了1小时,还是没想出来,果断弃疗, 最后的40分钟,我打完了第二题,接着又用了20分钟推敲出一种极其猥琐的式子来代替,可惜预处理的阶乘忘记 ...

  4. 【NOIP2016提高A组模拟9.17】数格子

    题目 分析 设表示每一行的状态,用一个4位的二进制来表示,当前这一行中的每一个位数对下一位有没有影响. 设\(f_{i,s}\)表示,做完了的i行,其状态为s,的方案数. 两个状态之间是否可以转移就留 ...

  5. 【NOIP2016提高A组模拟9.17】小a的强迫症

    题目 分析 题目要求第i种颜色的最后一个珠子要在第i+1种颜色的最后一个珠子之前, 那么我们从小到大枚举做到第i种,把第i种的最后一颗珠子取出,将剩下的\(num(i)-1\)个珠子插入已排好的前i- ...

  6. 【NOIP2016提高A组模拟8.17】(雅礼联考day1)总结

    考的还ok,暴力分很多,但有点意外的错误. 第一题找规律的题目,推了好久.100分 第二题dp,没想到. 第三题树状数组.比赛上打了个分段,准备拿60分,因为时间不够,没有对拍,其中有分段的20分莫名 ...

  7. 【NOIP2016提高A组模拟8.17】(雅礼联考day1)Binary

    题目 分析 首先每个数对\(2^i\)取模.也就是把每个数的第i位以后删去. 把它们放进树状数组里面. 那么当查询操作, 答案就位于区间\([2^i-x,2^{i-1}-1-x]\)中,直接查询就可以 ...

  8. 【NOIP2016提高A组模拟8.17】(雅礼联考day1)Value

    题目 分析 易证,最优的答案一定是按\(w_i\)从小到大放. 我们考虑dp, 先将w从小到大排个序,再设\(f_{i,j}\)表示当前做到第i个物品,已选择了j个物品的最大值.转移就是\[f_{i, ...

  9. 【NOIP2016提高A组模拟8.17】(雅礼联考day1)Matrix

    题目 分析 假设,我们从\(F_{i,2}\)出发,那么对\(F_{n,n}\)的贡献就是\(某个系数乘以a^{n-i}b^{n-1}r_i\): 同理,如果从\(F_{2,i}\)出发,那么对\(F ...

随机推荐

  1. day 90 跨域和CORS

    跨域和CORS   本节目录 一 跨域 二 CORS 三 xxx 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 跨域 同源策略(Same origin policy)是一种约定,它是 ...

  2. 升级MySQL5.7.22版本_总结记录

    目录 一. mysql5.7安装 0. 背景 1. 准备:下载安装包 2. 安装流程小结 3. 具体步骤 二. mysql5.7的一些变化 一. mysql5.7安装 0. 背景 之前用的5.6版本, ...

  3. sql实现查询某个字段在哪个表里 及结构是什么

    ) --数据库名 ) set @dbname2='aab' select @str = ' SELECT 表名=d.name,字段名=a.name,序号=a.column_id, 标识=is_iden ...

  4. swt java 内嵌ActiveX控件

    这里用的是SWT/JFace开发application中SWT自带的org.eclipse.swt.ole.win32 包可以支持内嵌OLE和ActiveX. 具体用法如下: //创建一个OleFra ...

  5. 使用PyCharm创建Django项目及基本配置

    https://segmentfault.com/a/1190000011576316 pycharm是个很不错的python开发工具,大大缩短了python项目的创建时间以及调试时间在使用pytho ...

  6. 针对Java集合类的小总结

    Java集合类包位于java.util下,有很多常用的数据结构:数组.链表.队列.栈.哈希表等等.了解不同的集合类的特性在开发过程中是比较重要的,感谢@兰亭风雨的专栏分析,这里我也根据自己的理解做轻度 ...

  7. 错误Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FSDataInputStream排查思路

    spark1(默认CDH自带版本)不存在这个问题,主要是升级了spark2(CDHparcel升级)版本安装后需要依赖到spark1的旧配置去读取hadoop集群的依赖包. 1./etc/spark2 ...

  8. xargs - 从标准输入重建并执行命令行

    总览 (SYNOPSIS) xargs [-0prtx] [-e[eof-str]] [-i[replace-str]] [-l[max-lines]] [-n max-args] [-s max-c ...

  9. js 阻止事件

    event.stopPropagation();//阻止事件冒泡 ,可阻止父类事件的发生 event.preventDefault();//阻止默认行为 如A标签

  10. Java类加载器浅述

    jdk默认提供了三种类加载器: 1.Bootstrap ClassLoader(引导类加载器): 将<JAVA_HOME>\lib目录下的类库加载到虚拟机内存中,用来加载java的核心库, ...