P3715 [BJOI2017]魔法咒语

AC自动机+dp+矩阵乘法

常规思路是按基本串建立AC自动机

然鹅这题是按禁忌串建立AC自动机

对后缀是禁忌的点以及它的失配点做上标记$(a[i].ed)$,到时候不访问。

基本串转化为自动机上的:设$p[j][i]$表示第$j$个节点加上第$i$个串会到的节点编号

在建好AC自动机后可以直接处理。

现在分类讨论(对,两份代码)

1.$L<=100,60pts$

直接在AC自动机上跑dp

设$f[j][i]$表示到点$j$长度为$i$的方案数

枚举基本串$1~k$,显然$f[p[j][k]][i+size[k]]+=f[j][i]$

$sz$表示AC自动机的节点数,则$ans=\sum_{i=0}^{sz}f[i][L]*[a[i].ed==0]$

2.基本词汇长度不超过$2,40pts$

开个$maxn*2$的矩阵,矩阵乘法瞎搞。

$f[i][L]=\sum_{j}f[j][l-1],j->i$

对于长度为2的情况,就开2倍的数组,用$i*2+1$暂时保存。

注意下标从0开始

(为啥我的常数这么大呢......)

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define N 105
const int mod=1e9+;
int ans,sz,n,m,L,siz[N],f[N][N],p[N][N];
char q[N],s[N][N];
queue <int> h; struct node{int nxt[],f,ed;}a[];
void add(){
scanf("%s",q);
int len=strlen(q),u=;
for(int i=;i<len;++i){
if(!a[u].nxt[q[i]-'a'])
a[u].nxt[q[i]-'a']=++sz;
u=a[u].nxt[q[i]-'a'];
}a[u].ed=;
}
void acbuild(){
for(int i=;i<;++i) if(a[].nxt[i]) h.push(a[].nxt[i]);
while(!h.empty()){
int x=h.front();h.pop();
for(int i=;i<;++i){
int &to=a[x].nxt[i];
if(to){
a[to].f=a[a[x].f].nxt[i];
a[to].ed|=a[a[to].f].ed;
h.push(to);
}else to=a[a[x].f].nxt[i];
}
}
} struct mat{
int A[][];
mat(){memset(A,,sizeof(A));}
mat operator * (mat &tmp) const{
mat c;int w=sz<<|;
for(int i=;i<=w;++i)
for(int j=;j<=w;++j)
for(int k=;k<=w;++k)
c.A[i][j]=(c.A[i][j]+1ll*A[i][k]*tmp.A[k][j]%mod)%mod;
return c;
}
};
mat Pow(mat x,int y){
mat rs;
for(int i=;i<=sz;++i)
rs.A[i<<][i<<]=;
for(;y;y>>=,x=x*x)
if(y&) rs=rs*x;
return rs;
} void task1(){
f[][]=;
for(int i=;i<L;++i)
for(int j=;j<=sz;++j)
if(f[j][i])
for(int k=;k<=n;++k)
if(p[j][k]!=-&&i+siz[k]<=L)
f[p[j][k]][i+siz[k]]=(f[p[j][k]][i+siz[k]]+f[j][i])%mod;
for(int i=;i<=sz;++i) if(!a[i].ed) ans=(ans+f[i][L])%mod;
}
void task2(){
mat res;
for(int i=;i<=sz;++i){
for(int j=;j<=n;++j)
if(p[i][j]!=-){
if(siz[j]==) ++res.A[p[i][j]<<][i<<];
else ++res.A[p[i][j]<<][i<<|];
}
res.A[i<<|][i<<]=;
}res=Pow(res,L);
for(int i=;i<=sz;++i) if(!a[i].ed) ans=(ans+res.A[i<<][])%mod;
}
int main(){
memset(p,-,sizeof(p));
scanf("%d%d%d",&n,&m,&L);
for(int i=;i<=n;++i) scanf("%s",s[i]),siz[i]=strlen(s[i]);
for(int i=;i<=m;++i) add();
acbuild();
for(int i=;i<=n;++i)
for(int j=,u=;j<=sz;u=++j){
for(int k=;k<siz[i]&&!a[u].ed;++k)
u=a[u].nxt[s[i][k]-'a'];
if(!a[u].ed) p[j][i]=u;
}
if(L<=) task1();
else task2();
printf("%d",ans);
return ;
}

bzoj4861 / P3715 [BJOI2017]魔法咒语的更多相关文章

  1. P3715 [BJOI2017]魔法咒语

    P3715 [BJOI2017]魔法咒语 用基本词汇组成\(L\)长度的单词,其中不能包含禁忌词汇 用禁忌词汇建强大的\(tire\)图 解决: 分类讨论,\(L<=100\)用普通dp暴力在\ ...

  2. [BJOI2017]魔法咒语 --- AC自动机 + 矩阵优化

    bzoj 4860   LOJ2180   洛谷P3175 [BJOI2017]魔法咒语 题目描述: Chandra 是一个魔法天才. 从一岁时接受火之教会洗礼之后,Chandra 就显示出对火元素无 ...

  3. Luogu-3250 [BJOI2017]魔法咒语(AC自动机,矩阵快速幂)

    Luogu-3250 [BJOI2017]魔法咒语(AC自动机,矩阵快速幂) 题目链接 题解: 多串匹配问题,很容易想到是AC自动机 先构建忌讳词语的AC自动机,构建时顺便记录一下这个点以及它的所有后 ...

  4. 【BZOJ4861】[Beijing2017]魔法咒语 矩阵乘法+AC自动机+DP

    [BZOJ4861][Beijing2017]魔法咒语 题意:别看BZ的题面了,去看LOJ的题面吧~ 题解:显然,数据范围明显的分成了两部分:一个是L很小,每个基本词汇长度未知:一个是L很大,每个基本 ...

  5. [BZOJ4861][BJOI2017]魔法咒语(AC自动机+矩阵优化DP)

    4861: [Beijing2017]魔法咒语 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 217  Solved: 105[Submit][Sta ...

  6. 【[BJOI2017]魔法咒语】

    矩阵乘法+\(AC\)自动机 是道很不错的题了 首先是前六十分,就是一个\(AC\)自动机上的套路\(dp\),设\(dp[i][j]\)表示匹配出的长度为\(i\)在自动机上位置为\(j\)的方案数 ...

  7. [BJOI2017]魔法咒语

    Description Chandra 是一个魔法天才. 从一岁时接受火之教会洗礼之后, Chandra 就显示出对火元素无与伦比的亲和力,轻而易举地学会种种晦涩难解的法术.这也多亏 Chandra ...

  8. AHOI2018训练日程(3.10~4.12)

    (总计:共90题) 3.10~3.16:17题 3.17~3.23:6题 3.24~3.30:17题 3.31~4.6:21题 4.7~4.12:29题 ZJOI&&FJOI(6题) ...

  9. AC 自动机学习笔记

    虽然 NOIp 原地爆炸了,目前进入 AFO 状态,但感觉省选还是要冲一把,所以现在又来开始颓字符串辣 首先先复习一个很早很早就学过但忘记的算法--自动 AC AC自动机. AC 自动机能够在 \(\ ...

随机推荐

  1. Mac上安装PHP、Apache、MySQL

    Mac自带php5.6版本,要升级到php7.3 步骤如下 1,brew 安装php ,如果没有安装,访问https://brew.sh/index_zh-cn安装在终端输入以下内容,不用指定安装ph ...

  2. Linux下修改MySQL数据库字符编码为UTF-8解决中文乱码

    由于MySQL编码原因会导致数据库出现乱码. 解决办法: 修改MySQL数据库字符编码为UTF-8,UTF-8包含全世界所有国家需要用到的字符,是国际编码. 具体操作: 1.进入MySQL控制台 &g ...

  3. 学习笔记 python 面向对象学习

    封装: 封装是面向对象的特征之一,是对象和类概念的主要特性. 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏. 继承: 继承是指这样 ...

  4. leetcode 93 复原IP地址

    IP地址,分成四段,每段是0-255,按照每段的长度分别为1,2,3下一段长度分别1,2,3再下一段......进行递归遍历,能满足条件的假如res中.比较难想到的就是假如有一段是三位的010是不符合 ...

  5. GO language

    看到有人说GO是未来10年的主流了,不论是速度迅速接近于C,还是语法简洁接近于C,结果尽然还是编译型的,不需要虚拟机,生成程序已经是本地字节码. 得,我不淡定了,这个不学,枉为程序员啊. 今天,讲讲l ...

  6. Windows(华硕/联想)笔记本上安装黑苹果与win双系统教程

    声明:电脑小白者请谨慎安装,如有需要可私聊或留言提供安装工具 首先说明:Windows PC的文件操作系统也就是磁盘格式是FAT32或 NTFS ,而 Mac 的文件操作系统格式是 HFS ,所以这时 ...

  7. 17.在自适应屏幕里通过JQ来获取宽高并赋给需要的

    在自适应屏幕里通过JQ来获取宽高并赋给需要的div. var height = document.documentElement.clientHeight; $(window).height();(同 ...

  8. laravel架构

    1.Laravel 5.1 中的异常处理器和HTTP异常处理实例教程 http://laravelacademy.org/post/1867.html 2.laravel 集成sentry,sentr ...

  9. Spark Streaming 002 统计单词的例子

    1.准备 事先在hdfs上创建两个目录: 保存上传数据的目录:hdfs://alamps:9000/library/SparkStreaming/data checkpoint的目录:hdfs://a ...

  10. sql 查询每科的前三名

    废话不多说,直接上脚本 CREATE TABLE [dbo].[Students]( ,) NOT NULL, ) NULL, ) NULL, [score] [int] NOT NULL, CONS ...