【题意】给定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+矩阵快速幂相关推荐

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

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

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

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

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

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

  4. BZOJ 2004 公交线路(状压DP+矩阵快速幂)

    注意到每个路线相邻车站的距离不超过K,也就是说我们可以对连续K个车站的状态进行状压. 然后状压DP一下,用矩阵快速幂加速运算即可. #include <stdio.h> #include ...

  5. bzoj 4818: [Sdoi2017]序列计数(DP+矩阵快速幂)

    4818: [Sdoi2017]序列计数 Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 769  Solved: 463 [Submit][Stat ...

  6. A. chino with string(ac自动机+floyd矩阵快速幂)

    LINK 有mmm个字符串,每个字符串有一定的分值(可能为负数) 求出一个长nnn的字符串sss使得它的价值最大,你只需要输出这个最大的价值. 价值定义为∑i=1mcii∗pointi\sum\lim ...

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

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

  8. BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )

    状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...

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

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

最新文章

  1. 无需SherlockActionbar的SlidingMenu使用详解(一)——通过SlidingMenu设置容器并解决滑动卡顿的问题
  2. IBatis.net动态SQL语句
  3. DL之DNN优化技术:利用Dropout(简介、使用、应用)优化方法提高DNN模型的性能
  4. 【Git1】指令,分支,ssh免密登录
  5. 利用WinPcap技术捕获数据包
  6. 一线大厂为什么对免费的开源项目这么热衷?
  7. python程序多次运行_Python内怎么使同一个.py文件多次运行?
  8. 大学生创新创业训练计划讲解(大创)
  9. 脱壳之aspack压缩壳
  10. 《阿里云服务器教程2》:如何远程连接linux系统阿里云服务器ECS
  11. 错误:Attempted read from closed stream尝试读取关闭的流!!!
  12. 配置MAWEN环境变量,总是出错
  13. Apple 设备尺寸
  14. electron与jquery起冲突,使用jquery报错解决方法
  15. matplotlib画图(完全版)
  16. 秒懂!什么是BI?热门BI工具?如何选择BI?
  17. 网格计算Grid Computing
  18. 设置input type=text的默认值
  19. 基于javaweb+mysql的校园招聘平台招聘管理系统(平台、企业、用户)
  20. C++检测内存泄漏方法

热门文章

  1. Soft:软件开发的简介(敏捷开发等6大软件开发模式)、软件测试的简介(单元测试/集成测试/系统测试/验收测试/回归测试、黑白灰功能测试、DEV等四套环境)、运维的简介之详细攻略
  2. MySQL-字符集和比较规则
  3. m1芯片能装mysql_Apple M1芯片电脑 软件兼容情况
  4. 带你快速入门AXI4总线--AXI4-Full篇(1)----AXI4-Full总线
  5. 公安通讯平台解决方案
  6. 【实用教程】一文学会安装Python环境,Python语言给我整起来
  7. [Cocos Creator 3.5]cc.Tween中easing包含哪些
  8. 班费管理系统数据库的设计与实现
  9. 技师计算机实际操作考试题库,技师操作题库_相关文章专题_写写帮文库
  10. STC12C5A60S2单片机实现ISP自动下载