LINK

有mmm个字符串,每个字符串有一定的分值(可能为负数)

求出一个长nnn的字符串sss使得它的价值最大,你只需要输出这个最大的价值.

价值定义为∑i=1mcii∗pointi\sum\limits_{i=1}^m ci_i*point_ii=1∑m​cii​∗pointi​

其中ciici_icii​表示给定的第iii个字符串在sss中的出现次数,pointipoint_ipointi​表示第iii个字符串的分值


对mmm个字符串建acacac自动机,每个节点预处理一个pointipoint_ipointi​表示以这个节点结尾的所有串的分值和

当然这个pointpointpoint要在failfailfail树上推标记累加

容易想到定义f[i][j]f[i][j]f[i][j]表示长度为iii的字符串在jjj节点的最大分值

转移方程一目了然(满足qqq节点到jjj节点有边)

f[i][j]=max⁡q−>j{f[i−1][q]+pointj}f[i][j]=\max_{q->j}\{f[i-1][q]+point_j\}f[i][j]=q−>jmax​{f[i−1][q]+pointj​}

然而n<=109n<=10^9n<=109,一般来说可以使用矩阵快速幂,但这里是max⁡\maxmax运算

初始矩阵为,长度是自动机上的节点个数,也就是相当于f[0][0],f[0][1]...f[0][id]f[0][0],f[0][1]...f[0][id]f[0][0],f[0][1]...f[0][id]的值

[0−inf⋯−inf]\begin{bmatrix} 0 & -inf & \cdots & -inf \\ \end{bmatrix} [0​−inf​⋯​−inf​]

转移矩阵为id∗idid*idid∗id的矩阵(下面用nnn表示ididid)

S=[x11x12⋯x1nx21x22⋯x2n⋮⋮⋱⋮xn1xn2⋯xnn]S= \begin{bmatrix} x_{11} & x_{12} & \cdots & x_{1n} \\ x_{21} & x_{22} & \cdots & x_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ x_{n1} & x_{n2} & \cdots\ & x_{nn} \\ \end{bmatrix} S=⎣⎢⎢⎢⎡​x11​x21​⋮xn1​​x12​x22​⋮xn2​​⋯⋯⋱⋯ ​x1n​x2n​⋮xnn​​⎦⎥⎥⎥⎤​

其中xi,jx_{i,j}xi,j​表示,若iii节点到jjj节点有边,xi,j=mxjx_{i,j}=mx_jxi,j​=mxj​

若iii节点到jjj节点无边,xi,j=−infx_{i,j}=-infxi,j​=−inf代表不能转移

这是一个外层max⁡\maxmax运算,内层+++运算的矩阵乘法

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 1e6+10;
const ll inf = 1e17;
int n,m,mx;
struct rce
{ll m[201][201];rce(){ memset( m,-0x3f3f3f3f,sizeof m); }
};
rce operator * ( rce a, rce b )
{rce ans;for(int i=0;i<=mx;i++)for(int j=0;j<=mx;j++)for(int k=0;k<=mx;k++)ans.m[i][j] = max( ans.m[i][j],a.m[i][k]+b.m[k][j] );return ans;
}
int zi[maxn][30],fail[maxn],id = 1;
ll point[maxn];
char a[maxn];
void insert(char a[],int val)
{int len = strlen( a+1 ), now = 0;for(int i=1;i<=len;i++){if( !zi[now][a[i]-'a'] )  zi[now][a[i]-'a'] = ++id;now = zi[now][a[i]-'a'];}point[now] += val;
}
void make_fail()
{queue<int>q;for(int i=0;i<=25;i++)if( zi[0][i] )  q.push( zi[0][i] );while( !q.empty() ){int u = q.front(); q.pop();point[u] += point[fail[u]];for(int i=0;i<=25;i++){int v = zi[u][i];if( v )fail[v] = zi[fail[u]][i], q.push( v );else  zi[u][i] = zi[fail[u]][i];}}
}
rce quick(rce x,int n)
{rce ans = x;for( ; n ; n>>=1,x=x*x )if( n&1 ) ans = ans*x;return ans;
}
int main()
{cin >> n >> m;for(int i=1;i<=m;i++){int val;scanf("%s%d",a+1,&val );insert( a,val );}make_fail(); mx = id;rce z;for(int i=0;i<=id;i++)for(int j=0;j<=25;j++){int v = zi[i][j];z.m[i][v] = point[v];}z = quick( z,n-1 );            ll ans = -inf;for(int i=0;i<=mx;i++)    ans = max( ans,z.m[0][i] );cout << ans;
}

A. chino with string(ac自动机+floyd矩阵快速幂)相关推荐

  1. 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂

    [题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...

  2. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  3. [BJOI2017]魔法咒语(AC自动机+DP+矩阵快速幂)

    文章目录 title solution code title solution 针对数据编程才是坠吊的!!! 观察数据,发现分隔数据的 L L L跨度过大,没有衔接--推测很有可能是分数据做法 ①:考 ...

  4. [BZOJ4861][Beijing2017]魔法咒语 AC自动机+动态规划+矩阵快速幂

    对忌讳词语构建AC自动机 Fi,j F_{i,j}表示长度为 i i,匹配到AC自动机第jj位的合法串方案数 当状态数少的时候用矩阵转移 #include <bits/stdc++.h> ...

  5. BZOJ.4180.字符串计数(后缀自动机 二分 矩阵快速幂/倍增Floyd)

    题目链接 先考虑 假设S确定,使构造S操作次数最小的方案应是:对T建SAM,S在SAM上匹配,如果有S的转移就转移,否则操作数++,回到根节点继续匹配S.即每次操作一定是一次极大匹配. 简单证明:假设 ...

  6. HDU5863 cjj's string game(DP + 矩阵快速幂)

    题目 Source http://acm.split.hdu.edu.cn/showproblem.php?pid=5863 Description cjj has k kinds of charac ...

  7. POJ 2778 DNA Sequence (自动机DP+矩阵快速幂)

    题意:给出m个致病DNA片段,求长为n且不含致病片段的DNA序列共有多少种. 数据范围:0 <= m <= 10,1 <= n <=2000000000 这题初看起来与上一题差 ...

  8. ZOJ 2317 Nice Patterns Strike Back(矩阵快速幂)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2317 题意:给你两种颜色,黑色和白色,填充n*m的方格,每个格子一种颜色, ...

  9. HDU - 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)

    题目链接:点击查看 题目大意:给出 n 个词根,现在要求出长度不大于 len 的单词中,有多少单词包含至少一个词根 题目分析:如果我们反过来想,也就是求出来总的单词数,然后减去不包含词根的单词数,剩下 ...

最新文章

  1. mysql忘记密码,如何重置密码
  2. PCB雕刻钻孔机制作
  3. [六省联考2017]分手是祝愿(期望+DP)
  4. Cannot find reference ‘PDFDocument‘ in ‘pdfparser.py‘
  5. 图论-欧拉图-欧拉回路-Euler-Fluery-Hierholzer-逐步插入回路法-DFS详解-并查集
  6. gitlab 迁移_无忌过招:手把手教你搭建自己的GitLab库
  7. mysql评论与回复一起查_mysql 查询所有评论以及回复
  8. UnityShader25:在Unity中实现泛光
  9. 10:Java人脸识别认证-Java API 实战
  10. 挑战程序设计竞赛 练习日记
  11. windows下创建本地局域网svnserver和gitserver
  12. f1c100s rootfs调试记录
  13. 后台管理系统架构成型
  14. 陈佼每周一蛋疼:“哼唱搜索”更像是个玩具
  15. 1000瓶药水和10只老鼠的问题及其扩展
  16. 安装Dreamweaver CS5遇到的问题
  17. windows 10 连接android手机助手,手把手教你Win10手机助手怎么用
  18. 《组织行为学》读后感_20170803
  19. 中国经典营销案例—农夫山泉
  20. CVE-2022-27778漏洞修复

热门文章

  1. os.system获取返回值 python3 cmd 获取返回值
  2. 数组、特殊矩阵、稀疏矩阵、广义表
  3. UVA 10526 - Intellectual Property (后缀数组)
  4. ssd nvme sata_NVMe SSD与传统SATA SSD
  5. 不要只怀揣梦想,而是要努力实现梦想!
  6. 芸赞通天下沈杨——怀揣梦想,不断努力
  7. [野火]EBF i.MX6ULL
  8. matlab最基础教程(二):变量类型与赋值
  9. github基础教程
  10. python中input是什么_Python中input函数的用法是什么?_后端开发