题目传送门(内部题140)


输入格式

  前两行有两个长度相同的字符串,描述林先森花园上的字母。
  第三行一个字符串$S$。


输出格式

  输出一行一个整数,表示有多少种可能的蛇,对$10^9+7$取模。


样例

样例输入1:

rwby
ybwr
rwby

样例输出1:

4

样例输入2:

ooo
ooo
oo

样例输出2:

14


数据范围与提示

  对于$20\%$的数据,$n,|S|\leqslant 16$。
  对于$40\%$的数据,$n,|S|\leqslant 40$。
  对于$60\%$的数据,$n,|S|\leqslant 200$。
  对于$100\%$的数据,$1\leqslant n,|S|\leqslant 2,000$,输入中只包含小写字母。


题解

先来考虑路径蛇的路径,可以将其拆解成如下图中的三部分$\downarrow$

蛇一定是先向一个方向走$a$格,再回来;然后乱走(扭动着),然后再向另一个方向走$b$格,再回来。

一样不一样可以用哈希判断。

然后考虑$DP$,定义$dp[i]][j][k]$表示到了点$(i,j)$,匹配到了$k$的方案数。

避免出现环可以外层循环$k$。

为了方便,可以先默认向一个方向走;然后再把整张图翻转再跑一遍就好了。

注意蛇的长度为$1$和$2$的情况下需要特判。

时间复杂度:$\Theta(|S|^2)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
struct rec{int s,x,y;};
int a[2][2001],b[2001],n,s;
char ch[2001];
long long dp[2][2001][4001][2],ans;
unsigned long long hsh[2001],flag[2001]={1},has[2][2][2002];
unsigned long long ask(bool x,bool y,int l,int r){return y?has[x][y][r]-has[x][y][l+1]*flag[l-r+1]:has[x][y][r]-has[x][y][l-1]*flag[r-l+1];}
unsigned long long get(int l,int r){return hsh[r]-hsh[l-1]*flag[r-l+1];}
void work()
{
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
has[i][0][j]=has[i][0][j-1]*131+a[i][j];
for(int i=0;i<2;i++)
for(int j=n;j;j--)
has[i][1][j]=has[i][1][j+1]*131+a[i][j];
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
{
dp[i][j][1][0]=(a[i][j]==b[1]);
for(int k=2;k<=j;k++)
dp[i][j][k<<1][1]=(ask(i^1,1,j,j-k+1)==get(1,k))&&(ask(i,0,j-k+1,j)==get(k+1,k<<1));
}
for(int k=1;k<=s;k++)
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
{
if(a[i][j]!=b[k])continue;
dp[i][j][k][0]=(dp[i][j][k][0]+dp[i][j-1][k-1][0]+dp[i][j-1][k-1][1])%mod;
dp[i][j][k][1]=(dp[i][j][k][1]+dp[i^1][j][k-1][0])%mod;
}
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<=s;k++)
{
int res=(s-k)>>1;
if(!((s-k)&1)&&res!=1&&(s==k||(j+res<=n&&ask(i,0,j+1,j+res)==get(k+1,k+res)&&ask(i^1,1,j+res,j+1)==get(s-res+1,s))))
ans=(ans+dp[i][j][k][0]+dp[i][j][k][1])%mod;
}
}
int main()
{
scanf("%s",ch+1);n=strlen(ch+1);
for(int i=1;i<=n;i++)a[0][i]=ch[i]-'a'+1;
scanf("%s",ch+1);
for(int i=1;i<=n;i++)a[1][i]=ch[i]-'a'+1;
scanf("%s",ch+1);s=strlen(ch+1);
for(int i=1;i<=s;i++)
{
b[i]=ch[i]-'a'+1;
flag[i]=flag[i-1]*131;
hsh[i]=hsh[i-1]*131+b[i];
}
work();
reverse(a[0]+1,a[0]+n+1);
reverse(a[1]+1,a[1]+n+1);
memset(dp,0,sizeof(dp));
work();
if(s==1)
{
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
ans-=(a[i][j]==b[1]);
}
if(s==2)
{
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
ans-=(a[i][j]==b[1]&&a[i^1][j]==b[2]);
}
printf("%lld",ans);
return 0;
}

rp++

[CSP-S模拟测试]:蛇(DP+构造+哈希)的更多相关文章

  1. [CSP-S模拟测试]:序列(构造)

    题目描述 给定$N,A,B$,构造一个长度为$N$的排列,使得:$\bullet$排列长度为$N$:$\bullet$最长上升子序列长度为$A$:$\bullet$最长下降子序列长度为$B$.我们有$ ...

  2. csp-s模拟测试97

    csp-s模拟测试97 猿型毕露.水题一眼秒,火题切不动,还是太菜了. $T1$看了一会儿感觉$woc$期望题$T1??$假的吧??. $T2$秒. $T3$什么玩意儿. 40 01:24:46 00 ...

  3. Mockito:一个强大的用于Java开发的模拟测试框架

    https://blog.csdn.net/zhoudaxia/article/details/33056093 介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用 ...

  4. Mock 模拟测试简介及 Mockito 使用入门

    Mock 是什么mock 测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法.这个虚拟的对象就是mock对象.mock对象就是真实对象在调试期间的代 ...

  5. noi2019模拟测试赛(四十七)

    noi2019模拟测试赛(四十七) T1与运算(and) 题意: ​ 给你一个序列\(a_i\),定义\(f_i=a_1\&a_2\&\cdots\&a_i\),求这个序列的所 ...

  6. [考试反思]1109csp-s模拟测试106:撞词

    (撞哈希了用了模拟测试28的词,所以这次就叫撞词吧) 蓝色的0... 蓝色的0... 都该联赛了还能CE呢... 考试结束前15分钟左右,期望得分300 然后对拍发现T2伪了写了一个能拿90分的垃圾随 ...

  7. [考试反思]1003csp-s模拟测试58:沉淀

    稳住阵脚. 还可以. 至少想拿到的分都拿到了,最后一题的确因为不会按秩合并和线段树分治而想不出来. 对拍了,暴力都拍了.挺稳的. 但是其实也有波折,险些被卡内存. 如果内存使用不连续或申请的内存全部使 ...

  8. [考试反思]0814NOIP模拟测试21

    前两名是外校的240.220.kx和skyh拿到了190的[暴力打满]的好成绩. 我第5是170分,然而160分就是第19了. 在前一晚上刚刚爆炸完毕后,心态格外平稳. 想想前一天晚上的挣扎: 啊啊啊 ...

  9. springboot2.0入门(四)----mock模拟测试+单元测试

    一.本节主要记录模拟测试.单元测试: 二.mock 测试 1.1什么是Mock? 在面向对象程序设计中,模拟对象(英语:mock object,也译作模仿对象)是以可控的方式模拟真实对象行为的假的对象 ...

随机推荐

  1. jQuery可拖拽旋转的3D图片墙

    在线演示 本地下载

  2. 如何利用 CSS 的动画原理,创作一个乒乓球对打动画

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/rvgLzK 可交互视频教 ...

  3. 怎么快速写好看的手机menu菜单

    要达到这样的效果: <div class="menu"> <div class="menu-1"> <img alt=" ...

  4. 数据结构(三) 树和二叉树,以及Huffman树

    三.树和二叉树 1.树 2.二叉树 3.遍历二叉树和线索二叉树 4.赫夫曼树及应用 树和二叉树 树状结构是一种常用的非线性结构,元素之间有分支和层次关系,除了树根元素无前驱外,其它元素都有唯一前驱. ...

  5. All shortest paths between a set of nodes

    .big{font-size:larger} .small{font-size:smaller} .underline{text-decoration:underline} .overline{tex ...

  6. sql--ALTER

    ALTER TABLE 语句 ALTER TABLE 语句用于在已有的表中添加.修改或删除列. SQL ALTER TABLE 语法 如需在表中添加列,请使用下列语法: ALTER TABLE tab ...

  7. vue+element 使用Export2Excel导出表格组件

    下载表格组件是根据我自己的业务需求来封装的 使用的是vue中 xlsx 的插件,需要安装新的依赖及配置 仅供参考 不保证和你百分百匹配 安装依赖 npm install -S file-saver x ...

  8. 对ArrayList中的Person对象按照先年龄从大到小,相同年龄的再按照姓名(姓名是英文的)的字母顺序进行排序.

    ListDemo2.java ----------------- package com.fs.test; import java.util.ArrayList; import java.util.C ...

  9. python中re模块

    1.定义 正则表达式是一个特殊的字符序列,能方便的检查一个字符串是否与某种模式匹配.re模块使得python拥有全部的正则表达式功能. 2.用途 通过使用正则表达式,可以:测试字符串内的模式.—— 例 ...

  10. windows环境变量和相关命令操作

    1.很多程序在windows上运行都需要设置环境变量. 2.具体步骤 复制路径 打开系统设置 高级系统设置 环境变量 设置path 重启cmd 3.可以把路径设置成变量,这样就不用随时 改path而是 ...