【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂
【题意】给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量。(60%)n,m<=50,L<=100。(40%)原串长度为1或2,L<=10^18。
【算法】AC自动机+DP+矩阵快速幂
【题解】其实题意的数据范围不太清晰,反正开200个点就足够了。
因为要匹配禁忌串,所以对禁忌串集合建立AC自动机,标记禁忌串结尾节点,以及下传到所有能fail到的点(这些点访问到都相当于匹配了禁忌串)。
令f[i][j]表示匹配到节点i,长度为j的串的数量,先预处理a[i][j]表示节点 i 匹配第 j 个原串到达的节点编号,那么就有:
f [ a[i][j] ] [ L+size[j] ] += f [ i ] [ L ]
以上就是60%数据的做法,对于40%的数据使用矩阵快速幂。
假设原串长度均为1,那么DP的转移如下:
$$f[i][L]=\sum_{j}f[j][L-1]\ \ ,\ \ j \rightarrow i$$
这很容易用一个长度为第一维大小(AC自动机节点数)的矩阵维护转移,第L个列向量就是f[i][L]。
如果原串长度有2,那么再记录L-1即可。
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> #define ll long long using namespace std; const int maxn=5010,MOD=1e9+7; int n,m,a[maxn][110],ch[maxn][27],val[maxn],size[maxn],sz=0,fail[maxn]; ll L; char s[110][maxn],S[maxn]; queue<int>Q; void insert(char *s){int n=strlen(s),u=0;for(int i=0;i<n;i++){int c=s[i]-'a';if(!ch[u][c])ch[u][c]=++sz;u=ch[u][c];}val[u]++; } void AC_build(){for(int c=0;c<26;c++)if(ch[0][c])Q.push(ch[0][c]);while(!Q.empty()){int u=Q.front();Q.pop();for(int c=0;c<26;c++)if(ch[u][c]){fail[ch[u][c]]=ch[fail[u]][c];Q.push(ch[u][c]);val[ch[u][c]]|=val[fail[ch[u][c]]];// }else ch[u][c]=ch[fail[u]][c];} } int M(int x){return x>=MOD?x-MOD:x;} namespace Task1{int f[maxn][110];void solve(){f[0][0]=1;for(int l=0;l<L;l++){// for(int i=0;i<=sz;i++)if(f[i][l]){for(int j=1;j<=n;j++)if(~a[i][j]&&l+size[j]<=L){f[a[i][j]][l+size[j]]=M(f[a[i][j]][l+size[j]]+f[i][l]);}}}int ans=0;for(int i=0;i<=sz;i++)if(f[i][L]&&!val[i])ans=M(ans+f[i][L]);printf("%d",ans);} } namespace Task2{const int maxn=110;int N,A[maxn*2][maxn*2],ANS[maxn*2][maxn*2],c[maxn*2][maxn*2];void mul(int a[maxn*2][maxn*2],int b[maxn*2][maxn*2]){for(int i=0;i<=N;i++){for(int j=0;j<=N;j++){c[i][j]=0;for(int k=0;k<=N;k++)c[i][j]=M(c[i][j]+1ll*a[i][k]*b[k][j]%MOD);}}for(int i=0;i<=N;i++)for(int j=0;j<=N;j++)b[i][j]=c[i][j];}void solve(){N=sz*2+1;for(int i=0;i<=sz;i++){for(int j=1;j<=n;j++)if(~a[i][j]){if(size[j]==1)A[a[i][j]*2][i*2]++;else A[a[i][j]*2][i*2+1]++;}A[i*2+1][i*2]=1;}ANS[0][0]=1;while(L){if(L&1)mul(A,ANS);mul(A,A);L>>=1;}int ans=0;for(int i=0;i<=sz;i++)if(!val[i])ans=M(ans+ANS[i*2][0]);printf("%d",ans);} } int main(){scanf("%d%d%lld",&n,&m,&L);for(int i=1;i<=n;i++)scanf("%s",s[i]);for(int i=1;i<=m;i++){scanf("%s",S);insert(S);}AC_build();memset(a,-1,sizeof(a));for(int k=1;k<=n;k++){size[k]=strlen(s[k]);for(int i=0;i<=sz;i++){int u=i;for(int j=0;j<size[k];j++)if(!val[u])u=ch[u][s[k][j]-'a'];else break;if(!val[u])a[i][k]=u;}}if(L<=100)Task1::solve();elseTask2::solve();return 0; }
View Code
转载于:https://www.cnblogs.com/onioncyc/p/8548841.html
【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂相关推荐
- [BZOJ4861][Beijing2017]魔法咒语 AC自动机+动态规划+矩阵快速幂
对忌讳词语构建AC自动机 Fi,j F_{i,j}表示长度为 i i,匹配到AC自动机第jj位的合法串方案数 当状态数少的时候用矩阵转移 #include <bits/stdc++.h> ...
- [BJOI2017]魔法咒语(AC自动机+DP+矩阵快速幂)
文章目录 title solution code title solution 针对数据编程才是坠吊的!!! 观察数据,发现分隔数据的 L L L跨度过大,没有衔接--推测很有可能是分数据做法 ①:考 ...
- 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂
[题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...
- BZOJ 2004 公交线路(状压DP+矩阵快速幂)
注意到每个路线相邻车站的距离不超过K,也就是说我们可以对连续K个车站的状态进行状压. 然后状压DP一下,用矩阵快速幂加速运算即可. #include <stdio.h> #include ...
- bzoj 4818: [Sdoi2017]序列计数(DP+矩阵快速幂)
4818: [Sdoi2017]序列计数 Time Limit: 30 Sec Memory Limit: 128 MB Submit: 769 Solved: 463 [Submit][Stat ...
- A. chino with string(ac自动机+floyd矩阵快速幂)
LINK 有mmm个字符串,每个字符串有一定的分值(可能为负数) 求出一个长nnn的字符串sss使得它的价值最大,你只需要输出这个最大的价值. 价值定义为∑i=1mcii∗pointi\sum\lim ...
- BZOJ.4180.字符串计数(后缀自动机 二分 矩阵快速幂/倍增Floyd)
题目链接 先考虑 假设S确定,使构造S操作次数最小的方案应是:对T建SAM,S在SAM上匹配,如果有S的转移就转移,否则操作数++,回到根节点继续匹配S.即每次操作一定是一次极大匹配. 简单证明:假设 ...
- BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )
状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...
- POJ 2778 DNA Sequence (自动机DP+矩阵快速幂)
题意:给出m个致病DNA片段,求长为n且不含致病片段的DNA序列共有多少种. 数据范围:0 <= m <= 10,1 <= n <=2000000000 这题初看起来与上一题差 ...
最新文章
- 无需SherlockActionbar的SlidingMenu使用详解(一)——通过SlidingMenu设置容器并解决滑动卡顿的问题
- IBatis.net动态SQL语句
- DL之DNN优化技术:利用Dropout(简介、使用、应用)优化方法提高DNN模型的性能
- 【Git1】指令,分支,ssh免密登录
- 利用WinPcap技术捕获数据包
- 一线大厂为什么对免费的开源项目这么热衷?
- python程序多次运行_Python内怎么使同一个.py文件多次运行?
- 大学生创新创业训练计划讲解(大创)
- 脱壳之aspack压缩壳
- 《阿里云服务器教程2》:如何远程连接linux系统阿里云服务器ECS
- 错误:Attempted read from closed stream尝试读取关闭的流!!!
- 配置MAWEN环境变量,总是出错
- Apple 设备尺寸
- electron与jquery起冲突,使用jquery报错解决方法
- matplotlib画图(完全版)
- 秒懂!什么是BI?热门BI工具?如何选择BI?
- 网格计算Grid Computing
- 设置input type=text的默认值
- 基于javaweb+mysql的校园招聘平台招聘管理系统(平台、企业、用户)
- C++检测内存泄漏方法
热门文章
- Soft:软件开发的简介(敏捷开发等6大软件开发模式)、软件测试的简介(单元测试/集成测试/系统测试/验收测试/回归测试、黑白灰功能测试、DEV等四套环境)、运维的简介之详细攻略
- MySQL-字符集和比较规则
- m1芯片能装mysql_Apple M1芯片电脑 软件兼容情况
- 带你快速入门AXI4总线--AXI4-Full篇(1)----AXI4-Full总线
- 公安通讯平台解决方案
- 【实用教程】一文学会安装Python环境,Python语言给我整起来
- [Cocos Creator 3.5]cc.Tween中easing包含哪些
- 班费管理系统数据库的设计与实现
- 技师计算机实际操作考试题库,技师操作题库_相关文章专题_写写帮文库
- STC12C5A60S2单片机实现ISP自动下载