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. 2017年9月22日作业 c++算术运算符 自增 自减 逻辑运算符 位运算符 条件运算符(三元运算符)

    作业1: c++算术运算符试题,分析下面程序的输出结果是什么 //第一个: int x=8999;int value=x*1000/1000; //第二个 int x=8999;int value=x ...

  2. 问题008:java 中代码块的风格有几种?单行注释可否嵌套?多行注释可否嵌套?

    有两种:一种是次行风格,英文称为next-line 一种是是行尾风格,英文称为 end-of-line 举例 行尾风格 public class HelloWorld{ public static v ...

  3. jQuery入门第一天-(一个菜鸟的不正经日常)

    jQuery的初步认识 菜鸟Q1:什么是jQuery? jQuery就是一个JavaScript函数库,没什么 特别的. 菜鸟Q2:jQuery能做什么?jQuery是做什么的? jQuery本身就是 ...

  4. 【原创】大数据量时生成DataFrame避免使用效率低的append方法

      转载请注明出处:https://www.cnblogs.com/oceanicstar/p/10900332.html      ★append方法可以很方便地拼接两个DataFrame df1. ...

  5. js时间转换

    1. 将时间戳转换成日期格式 // 简单的一句代码 var date = new Date(时间戳); //获取一个时间对象 /** 1. 下面是获取时间日期的方法,需要什么样的格式自己拼接起来就好了 ...

  6. Nginx http重定向到https时,post请求变为get的问题

    Http协议是有状态码的,比较熟悉的状态码是200,代表链接OK,还有404和403,一个是not found,另一个是forbidden.Not found不用多说,可能是地址栏输入有误,或者是网页 ...

  7. html下拉菜单栏代码

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  8. php扩展开发-快速上手

    系统环境CentOS release 6.5 (Final) PHP版本php-5.6.27 扩展开发需要有php环境及php的源代码,我的PHP安装目录/home/zhangxiaomin/stud ...

  9. VirtualBox下vim无法正常使用问题解决

    由原来的使用VMware转到使用Virtual Box,发现其vim编辑器不是特别好用,需要进行一下更改设置: 1.使用命令删除vim,sudo apt-get remove vim-common 2 ...

  10. Codeforces Round #460 (Div. 2)-B. Perfect Number

    B. Perfect Number time limit per test2 seconds memory limit per test256 megabytes Problem Descriptio ...