Description

一个\(2*n\)的方格矩阵,每个格子里有一个字符

给定一个长度为\(m\)的字符串\(s\)

求在方格矩阵中,有多少种走法能走出字符串\(s\)

一种合法的走法定义为:从任意一个位置出发,每次只能走到相邻的格子(common side),一个格子不能经过多次

\(n,m\le 2000\)

Analysis

刚做完一道百度之星题,跟这题很像,都是一个\(n^2​\)的dp

考虑从一个格子出发的走法:

比如一开始往右走,走若干步,往下,设当前走了\(k\)步

此时如果往右走,那么左边有一堵墙,还需走后\(m-k\)步

如果往左,就只能一直往左,走到中途匹配完,或者走回到起点的下面,然后往左走一步,那么右边有一堵墙,还需走后\(m-2k\)步

一开始往下走或往左走同理,都能经过一些简单的转化最后变成一个有墙的问题

而对于有墙的问题,dp就没有后效性了,一个简单的dp即可

我们求出每个格子出发,左边有墙的,走完后\(k\)的字符的方案数,往左出发同理求

最后在扫一遍统计从每个格子出发的方案数

字符串匹配用hash即可

Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int M=2e3+7;
const int Q=1e9+7; inline int pls(int x,int y){return (x+y)%Q;}
inline int mns(int x,int y){return pls(x,Q-y);}
inline int mul(int x,int y){return 1LL*x*y%Q;} int n,m;
char s[2][M],t[M];
int l[M][2][M],r[M][2][M];
bool bl[M][2][M],br[M][2][M]; struct Hsh{
static const int W=131; ull lf[M],rt[M],pw[M]; ull lfhsh(int x,int len){ int y=x+len-1;
return lf[y]-lf[x-1]*pw[len];
} ull rthsh(int len,int y){ int x=y-len+1;
return rt[x]-rt[y+1]*pw[len];
} void init(char *s,int n){ int i;
for (pw[0]=1,i=1;i<=n;++i) pw[i]=pw[i-1]*W;
for (lf[0]=0,i=1;i<=n;++i) lf[i]=lf[i-1]*W + s[i]-'a';
for (rt[n+1]=0,i=n;i>0;--i) rt[i]=rt[i+1]*W + s[i]-'a';
}
}hs[2],ht; void solve(){ int i,j,k; for(i=n;i>0;--i)
for(j=0;j<2;++j)
for(k=2;k<=m;k+=2)
br[i][j][k]= (i+k/2-1<=n && hs[j].lfhsh(i,k/2)==ht.lfhsh(m-k+1,k/2) && hs[j^1].rthsh(k/2,i+k/2-1)==ht.lfhsh(m-k/2+1,k/2)); for(i=1;i<=n;++i)
for(j=0;j<2;++j)
for(k=2;k<=m;k+=2)
bl[i][j][k]= (i-k/2+1>=1 && hs[j].rthsh(k/2,i)==ht.lfhsh(m-k+1,k/2) && hs[j^1].lfhsh(i-k/2+1,k/2)==ht.lfhsh(m-k/2+1,k/2)); r[n+1][0][0]=r[n+1][1][0]=1;
for(i=n;i>0;--i)
for(j=0;j<2;++j)
for(r[i][j][0]=1,k=1;k<=m;++k){
if(s[j][i]==t[m-k+1]) r[i][j][k]=pls(r[i][j][k],r[i+1][j][k-1]);
if(k>2 && s[j][i]==t[m-k+1] && s[j^1][i]==t[m-k+2]) r[i][j][k]=pls(r[i][j][k],r[i+1][j^1][k-2]);
if(br[i][j][k]) r[i][j][k]=pls(r[i][j][k],1);
} l[0][0][0]=l[0][1][0]=1;
for(i=1;i<=n;++i)
for(j=0;j<2;++j)
for(l[i][j][0]=1,k=1;k<=m;++k){
if(s[j][i]==t[m-k+1]) l[i][j][k]=pls(l[i][j][k],l[i-1][j][k-1]);
if(k>2 && s[j][i]==t[m-k+1] && s[j^1][i]==t[m-k+2]) l[i][j][k]=pls(l[i][j][k],l[i-1][j^1][k-2]);
if(bl[i][j][k]) l[i][j][k]=pls(l[i][j][k],1);
} for(i=n;i>0;--i)
for(j=0;j<2;++j)
for(k=2;k<=m;k+=2)
br[i][j][k]= (i+k/2-1<=n && hs[j].lfhsh(i,k/2)==ht.lfhsh(1,k/2) && hs[j^1].rthsh(k/2,i+k/2-1)==ht.lfhsh(k/2+1,k/2)); for(i=1;i<=n;++i)
for(j=0;j<2;++j)
for(k=2;k<=m;k+=2)
bl[i][j][k]= (i-k/2+1>=1 && hs[j].rthsh(k/2,i)==ht.lfhsh(1,k/2) && hs[j^1].lfhsh(i-k/2+1,k/2)==ht.lfhsh(k/2+1,k/2)); int ans=0;
for(i=1;i<=n;++i)
for(j=0;j<2;++j){
if(s[j][i]==t[1]) {ans=pls(ans,pls(l[i-1][j][m-1],r[i+1][j][m-1]));if(m==1) ans=mns(ans,1);}
for(k=2;k<=m;k+=2){
if(bl[i][j][k]) ans=pls(ans,r[i+1][j^1][m-k]);
if(br[i][j][k]) ans=pls(ans,l[i-1][j^1][m-k]);
}
if(m==2&&bl[i][j][2]) ans=mns(ans,1);
}
printf("%d\n",ans);
} int main(){ int i; scanf("%s",s[0]+1);
scanf("%s",s[1]+1);
scanf("%s",t+1); n=strlen(s[0]+1); m=strlen(t+1);
hs[0].init(s[0],n);
hs[1].init(s[1],n);
ht.init(t,m); solve(); return 0;
}

cf 613E - Puzzle Lover的更多相关文章

  1. CF613E Puzzle Lover

    题意 英文版题面 Problems Submit Status Standings Custom test .input-output-copier { font-size: 1.2rem; floa ...

  2. [Codeforces613E]Puzzle Lover

    Problem 给你2*n的格子,每个格子有一个字母,从任意一点出发,不重复的经过上下左右,生成要求的字符串.问有几种不同的走法. Solution 分三段,左U型.中间.右U型. 分别枚举左边和右边 ...

  3. 题解 CF613E Puzzle Lover

    解题思路 其实仔细观察我们可以发现路径一定是一个类似于下图的一个左括号之后中间随便反复曲折,然后右边在来一个右括号. 然后对于两个括号形状的东西其实是可以利用 Hash 来判等特殊处理的. 对于中间的 ...

  4. cf Round 613

    A.Peter and Snow Blower(计算几何) 给定一个点和一个多边形,求出这个多边形绕这个点旋转一圈后形成的面积.保证这个点不在多边形内. 画个图能明白 这个图形是一个圆环,那么就是这个 ...

  5. codeforces613E

    Puzzle Lover CodeForces - 613E Oleg Petrov loves crossword puzzles and every Thursday he buys his fa ...

  6. 多校联训 DP 专题

    [UR #20]跳蚤电话 将加边变为加点,方案数为 \((n-1)!\) 除以一个数,\(dp\) 每种方案要除的数之和即可. 点击查看代码 #include<bits/stdc++.h> ...

  7. CF 634A Island Puzzle

    A. Island Puzzle time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  8. CF 914 D. Bash and a Tough Math Puzzle

    D. Bash and a Tough Math Puzzle http://codeforces.com/contest/914/problem/D 题意: 单点修改,每次询问一段l~r区间能否去掉 ...

  9. CF 936C Lock Puzzle——构造

    题目:http://codeforces.com/contest/936/problem/C 玩了一个小时,只能想出 5*n 的方法. 经过一番观察?考虑这样构造:已经使得 A 串的一个后缀 = B ...

随机推荐

  1. 爬虫学习(三)——get请求参数解析

    get请求:        用户输入搜索的内容,发送请求,将请求的内容保存起来.        get请求的本质是在地址栏中输入参数进行的一种请求方式. 解析参数使用urllib.parse impo ...

  2. vs对某些网络错误的拦截

    在编写代码的过程中发现如果在写好网页中的文本框内写入js代码(以<script>1</script>输入为例) vs会自动拦截并报错,如图(密码中我也输入了<script ...

  3. Vue插槽

    插槽内容 Vue实现一套内容分发的API, 这套API基于当前的web组件规范草案,将元素作为承载分发内容的出口. <navigation-link url="/profile&quo ...

  4. 3 个用于数据科学的顶级 Python 库

    使用这些库把 Python 变成一个科学数据分析和建模工具. Python 的许多特性,比如开发效率.代码可读性.速度等使之成为了数据科学爱好者的首选编程语言.对于想要升级应用程序功能的数据科学家和机 ...

  5. 第15课 栏目的排序处理(组件化) Thinkphp5商城第四季

    目录 要实现的功能 思路: 视图层 控制器里: 扩展函数里 要实现的功能 用表单里的提交过来的sort数据,批量修改表里的排序值 界面效果: 思路: 视图层表单提交数据主键=>sort值 控制器 ...

  6. systick运用

    systick的原理前一篇博文有介绍,简而言之就是SysTick定时器是一个24位的倒计数,当倒计数为0时,将从RELOAD寄存器中取值作为定时器的初始值,同时可以选择在这个时候产生中断(异常号:15 ...

  7. Disharmony Trees HDU - 3015

    Disharmony Trees HDU - 3015 One day Sophia finds a very big square. There are n trees in the square. ...

  8. cf975d Ghosts

    ref #include <algorithm> #include <iostream> #include <cstdio> #include <map> ...

  9. MongoDB快速入门学习笔记2 MongoDB的概念及简单操作

    1.以下列举普通的关系型数据库和MongoDB数据库简单概念上的区别: 关系型数据库 MongoDB数据库 说明 database database 数据库 table collection 数据库表 ...

  10. 我对于js注入的理解

    资料:http://blog.csdn.net/gisredevelopment/article/details/41778671 js注入就是在前端利用使用js的地方 在这其中注入你写的js代码 使 ...