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. Jquery 就是怎么取得一个select的当前值

    <select id="cursel">: <option value="1">值1</option>: <optio ...

  2. NopCommerce(Core)学习目录

    1.NopCommerce下载运行 2.登录及权限 3.日志 4.依赖注入使用autofac 5.插件实现 ...

  3. tcl之list操作-lappend/lsearch/lsort/concat/split/join/

  4. tp5 使用paginate分页获取数据对象之后 如何对对象进行数据添加

    tp5 使用paginate分页获取数据对象之后 如何对对象进行数据添加 大家都知道,在使用tp5的paginate获取分页数据之后,得到的是一个数据对象,但有时会碰到要对数据对象进行二次加工的情况, ...

  5. 21.VUE学习之-操作data里的数组变异方法push&unshit&pop&shift的实例应用讲解

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

  6. 精通SpringBoot--整合druid监控SQL执行

    咳咳,今天我们做些简单而实用的东西,使用springboot 整合alibaba的driud数据库监控工具.alibaba已经提供了spring-boot-starter的jar包了.先看pom.xm ...

  7. 如何将emoji表情存放到mysql数据库中

    昨晚在爬取猫眼电影评论时在将评论信息插入到数据库中时出现问题,总是在插入一条数据时就会报错: 看着应该时字符编码的问题,比如新建的数据库新建的表,默认字符编码是:Latin1, 这种编码是无法插入中文 ...

  8. 权限组件(15):rbac的使用文档和在业务中的应用

    这里用主机管理系统当做示例. 一.将rbac组件拷贝到项目中. 注意: rbac自己的静态文件.layout.html(被继承的模板).bootstrap.fontsize.公共的css.jquery ...

  9. [Poj1273]Drainage Ditches(网络流)

    Description 给图,求最大流 最大流模板题,这里用dinic Code #include <cstdio> #include <cstring> #include & ...

  10. jichu

    第 题 请编写函数 fun,其功能时:计算并输出当 x<0.97 时下列多项式的值,直到| sn-s(n-)|<0.000001 为止. Sn=+.5x+)/!x()+…+)()…..() ...