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. vue watch 监听element upload组件上传成功返回的url列表

    因为 on-success 上传成功返回的是一个异步的结果....如果父组件需要这个结果的话 必须用watch 监听 然后里面建立一个 save()方法 save方法里面再调用接口 传需要的上传之后的 ...

  2. linux curl命令如何上传本地文件夹和下载文件

    本地有一个文件夹为my_dir,里面有四个文件,分别是test1.txt,user_account,tools_user,plans 要把这个my_dir文件夹传到ftp 192.168.8.251 ...

  3. [Leetcode] Template to rotate matrix

    Rotate the image by 90 degrees (clockwise). Given input matrix = [ [1,2,3,4], [5,6,7,8], [9,10,11,12 ...

  4. Java后台+数据库+Java web前端(新手)

    实现简单页面上对数据的增删改查:Java后台+数据库表+Jsp前端网页设计 这里做一个简单的学生课程信息管理系统,做之前一定要先有自己的思路,要不然对新手来说,很容易乱的. 另有一完整的代码可供参考, ...

  5. java获取请求的url地址

    1.获取全路径request.getRequestURL(); //得到http://localhost:8888/CRM/loginController/login 2.获取协议名和域名reques ...

  6. NodeJs--HTTP源码分析

    在github上按下按键t,就可以呼出仓库搜索的面板(在大型项目中方便检索文件),检索出http.js文件检索出来,通过ctrl+F来搜索某个方法. _http_outgoing 带下划线的是私有模块 ...

  7. cocos2d-X JS 获取cocostudio中的UI组件

    1.先加载cocostudio导出的json文件,代码如下所示: var dong = ccs.load("res/Login.json"); //_login.setPositi ...

  8. StackExchange.Redis在net中使用

    redis 官网https://redis.io redis 下载  进入下载页面  https://redis.io/download https://github.com/MicrosoftArc ...

  9. mybatis核心文件详解

    MyBatis配置文件详解 configuration  这是配置文件的根元素标签,所有的其他元素都要在这个标签下使用. environments   用于管理所有环境,并可以指定默认使用哪个环境,通 ...

  10. node.js初识03

    node中的url var http = require("http"); var url = require("url"); var server = htt ...