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. Oracle 事务 锁

    一. 事务 是一系列的数据库操作,是数据库应用的基本逻辑单位以及并发控制的基本单位.所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位. 要将有组语句作为事务考 ...

  2. 20180909 解析JS Cookie的设置,获取和检索

    引用: JavaScript Cookie - by runoob.com Cookie是储存在电脑文本文件中的数据,用于保存访问者的信息,并可以在下次打开页面时引用. 页面在设置/引用访问者信息时, ...

  3. Android驱动开发5-7总结

    Android深度探索5-7章总结 介绍了S3C6410开发板的功能,开发板的不同主要是在烧录嵌入式系统的方式不同,以及如何在此开发板上安装Android.紧接着学到介绍到如何在多种平台,使用多种方式 ...

  4. 第六篇:python中numpy.zeros(np.zeros)的使用方法

    用法:zeros(shape, dtype=float, order='C') 返回:返回来一个给定形状和类型的用0填充的数组: 参数:shape:形状 dtype:数据类型,可选参数,默认numpy ...

  5. Date.prototype.Format---对Date的扩展

    // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s).季度(q) 可以用 1-2 个占位符, // 年(y)可以用 1-4 个占 ...

  6. 极路由安装SS,SSR,搬运,侵权删除

    打开路由器的开发者模式 使用SSH,登录到路由器后台 复制以下代码,粘贴即可 cd /tmp $ echo "127.0.0.1 hiwifiss.ml" > /etc/ho ...

  7. 学习Pytbon第八天,文件的操作

    文件的常用操作字符 data=open('月亮代表我的心',encoding='utf-8').read() f=open('月亮代表我的心',encoding='utf-8')#提取内存对象也叫文件 ...

  8. activity切换交互动画

    activity切换的时候,想要有动画,那么... 1.想要有效果的activity设置theme <activity android:name=".MainActivity" ...

  9. Docker背后的内核知识(二)

    cgroups资源限制 上一节中Docker背后的内核知识(一),我们了解了Docker背后使用的资源隔离技术namespace,通过系统调用构建了一个相对隔离的shell环境,也可以称之为简单的“容 ...

  10. Redis实现之AOF持久化

    AOF持久化 除了RDB持久化功能之外,Redis还提供了AOF(Append Only File)持久化功能,与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Red ...