4861: [Beijing2017]魔法咒语

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 217  Solved: 105
[Submit][Status][Discuss]

Description

Chandra 是一个魔法天才。
从一岁时接受火之教会洗礼之后, Chandra 就显示出对火元素无与伦比的亲和力,轻而易举地学会种种晦涩难解
的法术。这也多亏 Chandra 有着常人难以企及的语言天赋,让她能轻松流利地说出咒语中那些极其拗口的魔法词
汇。直到十四岁,开始学习威力强大的禁咒法术时, Chandra 才遇到了障碍。根据火之魔法规则,禁咒的构成单
位是 N 个基本词汇。施法时只要凝聚精神力,说出一段用这些词语组成的长度恰好等于 L 的语言,就能释放威力
超乎想象的火法术。过去的魔法师们总结了几种表达起来最连贯的组合方式,方便施法者以最快语速完成法术。但
具有魔法和语言双重天才的 Chandra 不满足于这几种流传下来的禁咒,因为她可以毫无困难地说出普通人几乎不
可能表达的禁咒语句。然而,在实际施法时, Chandra 发现有些自创禁咒念出后不但没有预期效果,反而会使自
己的精神力迅速枯竭,十分难受。这个问题令 Chandra 万分不解。她大量阅读典籍,到处走访魔法学者,并且不
顾精神折磨一次又一次尝试新咒语,希望找出问题的答案。很多年过去了,在一次远古遗迹探险中, Chandra 意
外闯进了火之神艾利克斯的不知名神殿。根据岩土特征分析,神殿应该有上万年的历史,这是极其罕见的。 Chand
ra 小心翼翼地四处探索,沿着魔力流动来到一间密室。她看见密室中央悬浮着一本书籍。在魔法保护下书籍状况
完好。精通上古语言的 Chandra 读过此书,终于解开了多年的困惑。禁咒法术之所以威力强大,是因为咒语借用
了火之神艾利克斯的神力。这本书里记载了艾利克斯生平忌讳的 M 个词语,比如情敌的名字、讨厌的植物等等。
使用禁咒法术时,如果语言中含有任何忌讳词语,就会触怒神力而失效,施法者也一并遭受惩罚。例如,若 ”ban
ana” 是唯一的忌讳词语, “an”、 ”ban”、 ”analysis” 是基本词汇,禁咒长度须是 11, 则“bananalys
is” 是无效法术, ”analysisban”、 ”anbanbanban”是两个有效法术。注意:一个基本词汇在禁咒法术中可
以出现零次、 一次或多次;只要组成方式不同就认为是不同的禁咒法术,即使书写形式相同。谜题破解, Chandr
a 心情大好。她决定计算一共有多少种有效的禁咒法术。由于答案可能很大,你只需要输出答案模 1,000,000,007
 的结果。

Input

第一行,三个正整数 N, M, L。
接下来 N 行,每行一个只含小写英文字母的字符串,表示一个基本词汇。
接下来 M 行,每行一个只含小写英文字母的字符串,表示一个忌讳词语。
对于60%的数据1<=N,M<=50,L<=100
对于另40%数据基本词汇长度不超过2,L<=10^8

Output

仅一行,一个整数,表示答案(模 10^9+7)。

Sample Input

4 2 10
boom
oo
ooh
bang
ob
mo

Sample Output

14
【样例解释 】
有效的禁咒法术共有 14 种:boom/bang/oo,oo/oo/oo/oo/oo,oo/oo/ooh/ooh,
oo/ooh/oo/ooh, oo/ooh/ooh/oo, ooh/oo/oo/ooh, ooh/oo/ooh/oo,
ooh/ooh/boom, ooh/ooh/oo/oo, ooh/ooh/bang, ooh/bang/ooh,
bang/oo/oo/oo, bang/ooh/ooh, bang/bang/oo。

HINT

Source

[Submit][Status][Discuss]

前60分直接建出自动机套路DP,中间20分直接上矩阵快速幂,关键就是最后20分,单词长度不确定导致无法使用矩阵乘法的结合律。

回忆矩阵加速求fibonacci的时候,行向量矩阵同时记录了f[i-1]和f[i],那么这题也可以类似这样做,将矩阵扩大一倍即可。

一开始矩阵构造错了调了一个上午。。我怎么这么弱啊。。https://www.luogu.org/blog/ShadowassIIXVIIIIV/solution-p3715

#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
using namespace std; const int N=,mod=;
char s[N][N],p[N][N];
int n,m,L,ans,mx,S,nd,w[N],q[N],fail[N],len[N],to[N][N],ch[N][],f[N][N]; struct M{ int a[N][N]; M(){ memset(a,,sizeof(a)); }}T,res;
void mul(M &a,M b){
M c;
rep(i,,S) rep(j,,S) rep(k,,S) c.a[i][k]=(c.a[i][k]+1ll*a.a[i][j]*b.a[j][k])%mod;
rep(i,,S) rep(j,,S) a.a[i][j]=c.a[i][j];
} M ksm(M a,int b){
M res;
rep(i,,S) res.a[i][i]=;
for (; b; mul(a,a),b>>=)
if (b & ) mul(res,a);
return res;
} void ins(char s[]){
int x=,n=strlen(s);
for (int i=; i<n; i++){
int t=s[i]-'a'+;
if (!ch[x][t]) ch[x][t]=++nd;
x=ch[x][t];
}
w[x]=;
} void bfs(){
int st=,ed=;
rep(i,,) if (ch[][i]) q[++ed]=ch[][i];
while (st!=ed){
int x=q[++st];
rep(i,,) if (ch[x][i]) q[++ed]=ch[x][i],fail[ch[x][i]]=ch[fail[x]][i];
else ch[x][i]=ch[fail[x]][i];
w[x]|=w[fail[x]];
}
} int main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%d%d%d",&n,&m,&L);
rep(i,,n) scanf("%s",s[i]),len[i]=strlen(s[i]),mx=max(mx,len[i]);
rep(i,,m) scanf("%s",p[i]),ins(p[i]);
bfs();
rep(i,,nd){
rep(j,,n){
if (w[i]) { to[i][j]=-; continue; }
int x=i;
for (int k=; k<len[j]; k++){
x=ch[x][(int)s[j][k]-'a'+];
if (w[x]) { to[i][j]=-; break; }
}
if (~to[i][j]) to[i][j]=x;
}
}
if (L<=){
f[][]=;
for (int i=; i<L; i++)
rep(x,,nd) rep(j,,n)
if (i+len[j]<=L && ~to[x][j]) f[i+len[j]][to[x][j]]=(f[i+len[j]][to[x][j]]+f[i][x])%mod;
rep(i,,nd) ans=(ans+f[L][i])%mod;
printf("%d\n",ans);
}else{
rep(i,,nd) rep(j,,n)
if (~to[i][j]){
if (len[j]==) T.a[i+nd+][to[i][j]+nd+]++; else T.a[i][to[i][j]+nd+]++;
}
rep(i,,nd) T.a[i+nd+][i]=;
res.a[][nd+]=; S=*nd+; mul(res,ksm(T,L));
rep(i,nd+,S) ans=(ans+res.a[][i])%mod;
printf("%d\n",ans);
}
return ;
}

[BZOJ4861][BJOI2017]魔法咒语(AC自动机+矩阵优化DP)的更多相关文章

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

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

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

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

  3. [BJOI2011]禁忌 --- AC自动机 + 矩阵优化 + 期望

    bzoj 2553 [BJOI2011]禁忌 题目描述: Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平.而后,Koishi ...

  4. POJ2278 DNA Sequence —— AC自动机 + 矩阵优化

    题目链接:https://vjudge.net/problem/POJ-2778 DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Tota ...

  5. POJ 2778 (AC自动机+矩阵乘法)

    POJ 2778 DNA Sequence Problem : 给m个只含有(A,G,C,T)的模式串(m <= 10, len <=10), 询问所有长度为n的只含有(A,G,C,T)的 ...

  6. hdu 4057--Rescue the Rabbit(AC自动机+状压DP)

    题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...

  7. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  8. spoj 1676 AC自动机+矩阵快速

    Text Generator Time Limit: 1386MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Submi ...

  9. 矩阵优化dp

    链接:https://www.luogu.org/problemnew/show/P1939 题解: 矩阵优化dp模板题 搞清楚矩阵是怎么乘的构造一下矩阵就很简单了 代码: #include < ...

随机推荐

  1. Linux while 和 read 的用法

    Reference: [ linux man doc ] [ CSDN roler_ ] [ Reads from the file descriptor] read 命令说明 SYNTAX : re ...

  2. Vuejs - 深入浅出响应式系统

    Vue 最独特的特性之一,是其非侵入性的响应式系统.数据模型仅仅是普通的 Javascript 对象.而当你修改它们时,视图会进行更新.这使得状态管理非常简单直接,不过理解其工作原理同样非常重要,这样 ...

  3. 24、redis中的sentinel的作用?

    redis中的sentinel的作用? Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Re ...

  4. CART算法(转)

    来源:http://www.cnblogs.com/pinard/p/6053344.html 作者:刘建平Pinard 对于C4.5算法,我们也提到了它的不足,比如模型是用较为复杂的熵来度量,使用了 ...

  5. linux系统引导流程

    1.固件:硬件和软件结合.加电自检是我们按下电源会检测硬件像cpu.内存.网卡等信息.(从硬件层次检测硬件是否可用) 固件设置实例:设置时间 软件时间和硬件时间: [root@VM_0_12_cent ...

  6. 利用Python 发送邮件

    概要 我们都知道SMTP(简单邮件传输协议),是一组用于从原地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式.SMTP规定电子邮件应该如何格式化.如何加密,以及如何在邮件服务器之间传递.SMT ...

  7. Django【进阶】数据库查询性能相关

    之前项目中没有考虑过数据库查询关于效率的问题,如果请求量大,数据庞大,不考虑性能的话肯定不行.     tips:如图之前我们遇到过,当添加一张表时,作为原来表的外键,要给个默认值,现在我们写null ...

  8. win10远程桌面配置

    Win10连接远程桌面的时候提示您的凭证不工作该怎么办? http://www.cnblogs.com/zhuimengle/p/6048128.html 二.服务器端 1.依旧进入组策略,不过是在服 ...

  9. python基础===时间处理模块

    时间模块 Python中有很多方便我们处理时间信息的模块 time 模块 datetime 模块 pytz 模块 dateutil 模块 这里我们着重介绍的是前两种 time模块 time.time( ...

  10. 【bzoj3545】peaks

    离线一下,动态开点+线段树合并,然后权值线段树上询问kth即可. #include<bits/stdc++.h> ; *; using namespace std; ; inline in ...