n=40的01串,求有多少m=40的01串中包含它,包含的定义是存在子串有至多一个字符不相同

600组n=15的数据 15组n=40的数据,所以我们只能支持n^5的算法。

陷入两个比较有意思的坑:

1 如果手动构建fail树,建立两个并行的串,左串代表当前未使用那一个可以不相同的字符的名额,右串代表已经使用了这个名额,那么按照bfs m步的想法,左串可以通过“使用名额”到达右串,也可以通过“不使用名额”走一个fail,而右串一旦失配,只能在右串的对应位置进行fail。这样跑一遍矩阵乘法,复杂度是(2*n)^3

但是不对,因为假设右串失配了,可能距离一个点从左串跳过来已经过了很久了,那个名额已经可以再次使用了,所以它可以再跳回左串。这样就会导致我们失去一些答案。

2 如果插入n+1个串,代表原串,和原串第i个位置不同的串,这样点是n^3,那么矩阵乘法是n^6,还有一个logm的快速幂时间,复杂度会超

陷入了误区:快速幂一定比直接转移快。快速幂的快体现在将m转移到logm,但是二维矩阵的自乘是(点数^3)的,加一个快速幂的优化是从m(n*n)到logm(n*n*n)。

所以暴力插入n+1个串建树,暴力(n*n)^2的枚举边,跑m次转移。

L read() {L x;scanf("%lld" , &x) ; return x ; } ;

char s[50] ;

L c[40 * 40 + 5] ;
L a[40 * 40 + 5][40 * 40 + 5] ;
L b[40 * 40 + 5] ;
L n , m ; struct AC{
L next[40 * 40 + 5][2] , fail[40 * 40 + 5] , en[40 * 40 + 5] ;
L ro , to ;
L newnode() {
to++;
for(L i = 0 ; i < 2 ; i ++ ) next[to][i] = -1 ;
en[to] = 0 ;
return to ;
}
void init() {
to = -1 ;
ro = newnode() ;
}
void inse() {
L now = ro ;
for(L i = 1 ; i <= n ; i ++ ) {
if(next[now][s[i]-'0'] == -1) next[now][s[i]-'0'] = newnode();
now = next[now][s[i]-'0'];
}
en[now]++;
}
void build() {
queue<int>q;
fail[ro]=ro;
for(L i=0;i<2;i++){
if(next[ro][i] == -1) next[ro][i]=ro;
else {
fail[next[ro][i]]=ro;
q.push(next[ro][i]);
}
}
while(!q.empty()){
L now=q.front();q.pop();
for(L i=0;i<2;i++){
if(next[now][i]==-1)next[now][i] = next[fail[now]][i] ;
else {
fail[next[now][i]] = next[fail[now]][i];
q.push(next[now][i]);
}
}
}
}
void gao() {
inse() ;
for(int i = 1 ; i <= n ; i ++ ) {
s[i] = '0' + ((s[i] - '0') ^ 1) ;
inse();
s[i] = '0' + ((s[i] - '0') ^ 1) ;
}
build() ;
for(int i = 0 ; i <= to ; i ++ ) {
for(int j = 0 ; j <= 1 ; j ++ ) {
int v = next[i][j];
if(en[i] == 0)
a[i][v] ++ ;
}
}
for(int i = 0 ; i <= to ; i ++ ) {
if(en[i] != 0) a[i][i] += 2 ;
}
b[0] = 1 ;
for(int i = 1 ; i <= m ; i ++ ) {
memset(c, 0 , sizeof(c)) ;
for(int u = 0 ; u <= to ; u ++ ) {
for(int v = 0 ; v <= to ; v ++ ) {
c[v] += b[u] * a[u][v] ;
}
}
for(int j = 0 ; j <= to ; j ++ )
b[j] = c[j] ;
}
L ans = 0 ;
for(int i = 0 ; i <= to ; i ++ ) {
if(en[i] != 0) ans += b[i] ;
}
cout << ans << endl ;
} }ac; int main () { L t = read() ; while(t -- ) {
n = read() ; m = read() ;
scanf("%s" , s+1) ;
memset(a,0,sizeof(a)) ;
memset(b,0,sizeof(b)) ;
ac.init() ;
ac.gao() ;
}
}

  

2018 ICPC北京 H ac自动机的更多相关文章

  1. 2018 Arab Collegiate Programming Contest (ACPC 2018) E - Exciting Menus AC自动机

    E - Exciting Menus 建个AC自动机求个fail指针就好啦. #include<bits/stdc++.h> #define LL long long #define fi ...

  2. hihoCoder #1871 : Heshen's Account Book-字符串暴力模拟 自闭(getline()函数) (ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction B) 2018 ICPC 北京区域赛现场赛B

    P2 : Heshen's Account Book Time Limit:1000ms Case Time Limit:1000ms Memory Limit:512MB Description H ...

  3. hihoCoder #1870 : Jin Yong’s Wukong Ranking List-闭包传递(递归) (ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction A) 2018 ICPC 北京区域赛现场赛A

    P1 : Jin Yong’s Wukong Ranking List Time Limit:1000ms Case Time Limit:1000ms Memory Limit:512MB Desc ...

  4. 2016ACM/ICPC亚洲区沈阳站H - Guessing the Dice Roll HDU - 5955 ac自动机+概率dp+高斯消元

    http://acm.hdu.edu.cn/showproblem.php?pid=5955 题意:给你长度为l的n组数,每个数1-6,每次扔色子,问你每个串第一次被匹配的概率是多少 题解:先建成ac ...

  5. 2018 焦作网络赛 L Poor God Water ( AC自动机构造矩阵、BM求线性递推、手动构造矩阵、矩阵快速幂 )

    题目链接 题意 : 实际上可以转化一下题意 要求求出用三个不同元素的字符集例如 { 'A' .'B' .'C' } 构造出长度为 n 且不包含 AAA.BBB CCC.ACB BCA.CAC CBC ...

  6. 2019牛客多校八 H. How Many Schemes (AC自动机,树链剖分)

    大意: 给定树, 每条边有一个字符集合, 给定$m$个模式串, $q$个询问$(u,v)$, 对于路径$(u,v)$中的所有边, 每条边从对应字符集合中取一个字符, 得到一个串$s$, 求$s$至少包 ...

  7. 2018 ACM-ICPC 北京赛区小结 @ Reconquista

    Statistics TYPE: Onsite Contest NAME: 2018 - ICPC Regional - Asia EC - Beijing PLAT: Hihocoder TIME: ...

  8. 2016 年青岛网络赛---Family View(AC自动机)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5880 Problem Description Steam is a digital distribut ...

  9. 【HDU2825】Wireless Password (AC自动机+状压DP)

    Wireless Password Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u De ...

随机推荐

  1. Yii框架2.0 数据库操作初接触

    Yii2.0和Yii1.1版本的变动还是挺多的,我发现配置文件有许多不同,Yii1.1版本里有个main.php 好多信息是在这里配置的,比如默认控制器,数据库连接信息:Yii的数据库配置被单独拿出来 ...

  2. Androidstudio中导入内部依赖模块总结

    今天刚从GitHub上找了一个不错的项目,想要把它导入自己的项目中,过程中也遇到了一些小问题,总结一下,以便复习回顾!!!! 1.首先将从GitHub上下载的压缩包进行解压,找到其中的项目文件,直接复 ...

  3. 转载--菜鸟Linux上使用Github

    1.安装Git:Ctrl + Alt + T使用终端:使用命令 sudo apt-get install git 2.创建GitHub帐号:登陆git主页: https://github.com/,自 ...

  4. centos删除乱码名称的文件

    常规方法rm已经木有办法删除该文件了. 原理: 当文件名为乱码的时候,无法通过键盘输入文件名,所以在终端下就不能直接利用rm,mv等命令管理文件了.但是每个文件都有一个i节点号,可以通过i节点号来管理 ...

  5. RocketMQ 单机安装

    本章快速入门指南是在本地机器上设置 RocketMQ 消息传递系统以发送和接收消息的详细说明. 在这先对RocketMQ 做一个简单介绍. RocketMQ是一个纯java.分布式.队列模型的开源消息 ...

  6. 《你的SSD可以用100年,你造吗?》总结

    来自 http://www.ssdfans.com/?p=1778 上图是闪存的一个基本存储单元,由一种类NMOS的双层浮空栅 (Floating Gate) MOS管组成,用以存储一个bit(SLC ...

  7. 闪回事务(Flashback Transaction)

    到目前为止,介绍的所有功能均不会直接将数据恢复为“以前”的样子.闪回查询只是查看,闪回数据归档只是延伸了闪回查询的时间窗口,闪回事务查询虽然提供了撤销SQL,但是否执行及如何执行还需要管理员进一步手动 ...

  8. python 中字典的操作(增、删、改、查)

    字典是另一种可变容器模型,且可存储任意类型对象,下标从0开始,最后一个为-1. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({}) ...

  9. Debian中安装使用sudo命令

     Debian中安装使用sudo命令  sudo可以让非root用户具有管理员的权限,安装好的Debian后还不能使用sudo,需要使用root用户登陆后安装sudo命令.#apt-get insta ...

  10. vmware下安装centos7

    下载vmware http://down-www.newasp.net/pcdown/big/wm_pro_14_win.rar 下载centos7 https://www.centos.org/do ...