题目传送门(内部题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. Python 入门 之 类成员

    Python 入门 之 类成员 1.类的私有成员: 私有: 只能自己拥有 以 __ 开头就是私有内容 对于每一个类的成员而言都有两种形式: - 公有成员,在任何地方都能访问 - 私有成员,只有在类的内 ...

  2. python网络编程-socket套接字通信循环-粘包问题-struct模块-02

    前置知识 不同计算机程序之间数据的传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...

  3. WPF文本输入框关闭Win10输入法设置

    今天一个同事突然站起来给了我一个眼神,我就知道没啥好事.果然给我指出了一些bug,其中一个是这样的,密码输入框只能输入一个字符,再输入就输入不了. 这种降档次的错误咱也能出,果断夺过键盘,疯狂输入一番 ...

  4. 学习笔记--APIO 2018 二分专题 By wuvin

    前言: 在APIO 2018 Day2下午听wuvin讲二分,听了一上午的神仙,现在终于有可以听懂了. 专题: 平均边权最大 题目链接:https://www.questoj.cn/problem/3 ...

  5. QT多线程同步之QWaitcondition

    使用到多线程,无可避免的会遇到同步问题,qt提供几种同步线程的方法,在这里讲一下QWaitcondition的简单使用. 一.QWaitcondition,是通过一个线程达到某种条件来唤起另一个线程来 ...

  6. scala新版本学习(3)

    1.REPL:读取->求值->打印->循环.Scala程序将输入的内容快速的编译成为字节码,然后字节码文件交给Java虚拟机进行执行. 2.val是值不可变,var值可变.在变量声明 ...

  7. 应对Hadoop集群数据疯长,这里祭出了4个治理对策!

    一.背景 在目前规模比较大的互联网公司中,总数据量能达到10PB甚至几十PB数据量的公司,我认为中国已经有超过了20家了.而在这些公司中,也有很多家公司的 日数据增长达到100TB+ 了. 所以我们每 ...

  8. groovy程序设计

    /********* * groovy中Object类型存在隐式转换 可以不必使用as强转 */ Object munber = 9.343444 def number1 = 2 println mu ...

  9. leetcode297. 二叉树的序列化与反序列化

    代码 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * ...

  10. Rasa学习记录 01

    目录 Rasa的安装和简单的测试 什么是Rasa: 安装Rasa: 测试自带的数据 查看项目里的文件内容 举一反三(自己的第一个机器人) Rasa的安装和简单的测试 怪雨是新手,刚刚接触Rasa,以下 ...