Codeforces Round #362(Div1) D Legen...(AC自动机+矩阵快速幂)
题目大意:
给定一些开心串,每个串有一个开心值,构造一个串,每包含一次开心串就会获得一个开心值,求最大获得多少开心值。
题解:
首先先建立AC自动机。(建立fail指针的时候,对val要进行累加)
然后在AC自动机上跑dp
dp[i][j] = max(dp[i][j], dp[i-1][k] + v[j])
写成矩阵形式就是(Mat[i][j]表示从i到j最大获得的开心值)
C[i][j] = max(C[i][j], A[i][k]+B[k][j])
然后这个形式也可以用快速幂的形式加速!!
然后救过了!
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N = , maxc = ;
char str[];
struct Trie{
int Next[N][maxc], fail[N], tag[N];
long long val[N];
int root, L;
int newnode(){
for(int i = ; i < maxc; i++)
Next[L][i] = -;
tag[L++] = ;
return L-;
}
void init() { L = ; root = newnode(); }
void Insert(char* s, int len, int v){
int u = root;
for(int i = ; i < len; i++){
int c = s[i] - 'a';
if(Next[u][c] == -) Next[u][c] = newnode();
u = Next[u][c];
}
tag[u] = ;
val[u] += v;
}
void build(){
queue<int> Q;
fail[root] = root;
for(int i = ; i < maxc; i++){
if(Next[root][i] == -) Next[root][i] = root;
else {
fail[Next[root][i]] = root;
Q.push(Next[root][i]);
}
}
while(!Q.empty()){
int u = Q.front();
Q.pop();
val[u] += val[fail[u]];
for(int i = ; i < maxc; i++){
int &v = Next[u][i];
if(v == -){
v = Next[fail[u]][i];
} else {
Q.push(v);
fail[v] = Next[fail[u]][i];
}
}
}
}
}ac; struct Matrix{
long long Mat[][];
int n;
Matrix() {n = ; memset(Mat, , sizeof(Mat));}
Matrix(Matrix &B){
n = B.n;
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
Mat[i][j] = B.Mat[i][j];
}
Matrix operator +(const Matrix &B)const {
Matrix C;
C.n = n;
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++){
C.Mat[i][j] = -1e18;
for(int k = ; k <= n; k++)
C.Mat[i][j] = max(C.Mat[i][j], Mat[i][k] + B.Mat[k][j]);
}
return C;
}
void print(){
cout<<"*"<<endl;
for(int i = ; i <= n; i++){
for(int j = ; j <= n; j++) cout<<Mat[i][j]<<" ";
cout<<endl;
}
}
}A;
Matrix mypow(Matrix A, long long b)
{ Matrix ans = A; b--; for(; b; b >>= , A = A+A) if(b&) ans = ans+A; return ans;}
int n, val[];
long long l;
int main()
{
ac.init();
cin>>n>>l;
for(int i = ; i <= n; i++) scanf("%d", &val[i]);
for(int i = ; i <= n; i++){
cin>>str;
ac.Insert(str, strlen(str), val[i]);
}
ac.build();
A.n = ac.L-;
for(int i = ; i < ac.L; i++)
for(int j = ; j < ac.L; j++)
A.Mat[i][j] = -1e18;
for(int i = ; i < ac.L; i++){
for(int j = ; j < maxc; j++){
int v = ac.Next[i][j];
if(v == -) continue;
A.Mat[i][v] = ac.val[v];
}
}
A = mypow(A, l);
long long ans = -1e18;
for(int i = ; i < ac.L; i++) ans = max(ans, A.Mat[][i]);
cout<<ans<<endl;
return ;
}
Codeforces Round #362(Div1) D Legen...(AC自动机+矩阵快速幂)的更多相关文章
- POJ2778 DNA Sequence(AC自动机+矩阵快速幂)
题目给m个病毒串,问不包含病毒串的长度n的DNA片段有几个. 感觉这题好神,看了好久的题解. 所有病毒串构造一个AC自动机,这个AC自动机可以看作一张有向图,图上的每个顶点就是Trie树上的结点,每个 ...
- poj2778DNA Sequence (AC自动机+矩阵快速幂)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud DNA Sequence Time Limit: 1000MS Memory ...
- HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)
背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...
- POJ2778(SummerTrainingDay10-B AC自动机+矩阵快速幂)
DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17160 Accepted: 6616 Des ...
- poj2778 ac自动机+矩阵快速幂
给m个子串,求长度为n的不包含子串的母串数,最直接的应该是暴搜,肯定tle,考虑用ac自动机 将子串建成字典树,通过next表来构造矩阵,然后用矩阵快速幂求长度为n的数量 邻接矩阵https://we ...
- HDU 2243 考研路茫茫――单词情结 ——(AC自动机+矩阵快速幂)
和前几天做的AC自动机类似. 思路简单但是代码200余行.. 假设solve_sub(i)表示长度为i的不含危险单词的总数. 最终答案为用总数(26^1+26^2+...+26^n)减去(solve_ ...
- POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂
这两题属于AC自动机的第二种套路通过矩阵快速幂求方案数. 题意:给m个病毒字符串,问长度为n的DNA片段有多少种没有包含病毒串的. 根据AC自动机的tire图,我们可以获得一个可达矩阵. 关于这题的t ...
- 考研路茫茫——单词情结 HDU - 2243 AC自动机 && 矩阵快速幂
背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...
- POJ 2778 DNA Sequence(AC自动机 + 矩阵快速幂)题解
题意:给出m个模式串,要求你构造长度为n(n <= 2000000000)的主串,主串不包含模式串,问这样的主串有几个 思路:因为要不包含模式串,显然又是ac自动机.因为n很大,所以用dp不太好 ...
随机推荐
- 【CF543E】Listening to Music
[CF543E]Listening to Music 题面 洛谷 题目大意 给你一个长度为\(n\)序列\(a_i\),和一个常数\(m\),定义一个函数\(f(l,x)\)为\([l,l+m-1]\ ...
- 【LG4631】[APIO2018]Circle selection 选圆圈
[LG4631][APIO2018]Circle selection 选圆圈 题面 洛谷 题解 用\(kdt\)乱搞剪枝. 维护每个圆在\(x.y\)轴的坐标范围 相当于维护一个矩形的坐标范围为\([ ...
- mysql 错误代码 1248
1248 - Every derived table must have its own alias (MYSQL错误) 这句话的意思是说每个派生出来的表都必须有一个自己的别名,给派生表加上一个别名就 ...
- 高能福利 |"荐"者有份,有"福"同享
WeTest 导读 越来越多的开发者加入WeTest大家庭了,感谢大家一直以来的支持,WeTest又有新一步“大福利”赠送了! 即日起,参加WeTest用户推荐有礼活动,推荐者和被推荐者皆可获得福利. ...
- selenium webdriver API详解(三)
本系列主要讲解webdriver常用的API使用方法(注意:使用前请确认环境是否安装成功,浏览器驱动是否与谷歌浏览器版本对应) 一:获取页面元素的文本内容:text 例:获取我的博客名字文本内容 代码 ...
- 后台程序获取JPG/GIF/PNG图片宽度、高度
这是很久之前编写的代码,该代码是读取流数据指定位置的内容,获取图片的宽度.高度值. 由于系统更新,这些代码丢之不用,在这里存个档吧! 1. 获取gif图片宽度.高度.(binary_是图片流数据) ' ...
- mongodb windows 4 zip安装
安装mongoDB目的:学习Express,顺带mongodb. 本文目的: 4.0.2的mongodb在windows7上竟然安装不了. 没办法,用压缩包手动安装吧... 安装环境:win7sp1x ...
- PHPDoc 学习记录
https://zh.wikipedia.org/wiki/PHPDoc PHPDoc 是一个 PHP 版的 Javadoc.它是一种注释 PHP 代码的正式标准.它支持通过类似 phpDocumen ...
- Python:内建函数zip
1.语法 zip([iterable,...]) [说明]:iterable——一个或多个迭代器 2.功能 zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个的元组,然后返回由这 ...
- C++ Primer Plus学习:第一章
C++入门第一章:预备知识 C++简介 C++融合了三种不同的编程方式: C语言代表的过程性语言. C++在C语言基础上添加的类代表的面向对象语言. C++模板支持的泛型编程. C++简史 20世纪7 ...