[CSP-S模拟测试]:蛇(DP+构造+哈希)
题目传送门(内部题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+构造+哈希)的更多相关文章
- [CSP-S模拟测试]:序列(构造)
题目描述 给定$N,A,B$,构造一个长度为$N$的排列,使得:$\bullet$排列长度为$N$:$\bullet$最长上升子序列长度为$A$:$\bullet$最长下降子序列长度为$B$.我们有$ ...
- csp-s模拟测试97
csp-s模拟测试97 猿型毕露.水题一眼秒,火题切不动,还是太菜了. $T1$看了一会儿感觉$woc$期望题$T1??$假的吧??. $T2$秒. $T3$什么玩意儿. 40 01:24:46 00 ...
- Mockito:一个强大的用于Java开发的模拟测试框架
https://blog.csdn.net/zhoudaxia/article/details/33056093 介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用 ...
- Mock 模拟测试简介及 Mockito 使用入门
Mock 是什么mock 测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法.这个虚拟的对象就是mock对象.mock对象就是真实对象在调试期间的代 ...
- noi2019模拟测试赛(四十七)
noi2019模拟测试赛(四十七) T1与运算(and) 题意: 给你一个序列\(a_i\),定义\(f_i=a_1\&a_2\&\cdots\&a_i\),求这个序列的所 ...
- [考试反思]1109csp-s模拟测试106:撞词
(撞哈希了用了模拟测试28的词,所以这次就叫撞词吧) 蓝色的0... 蓝色的0... 都该联赛了还能CE呢... 考试结束前15分钟左右,期望得分300 然后对拍发现T2伪了写了一个能拿90分的垃圾随 ...
- [考试反思]1003csp-s模拟测试58:沉淀
稳住阵脚. 还可以. 至少想拿到的分都拿到了,最后一题的确因为不会按秩合并和线段树分治而想不出来. 对拍了,暴力都拍了.挺稳的. 但是其实也有波折,险些被卡内存. 如果内存使用不连续或申请的内存全部使 ...
- [考试反思]0814NOIP模拟测试21
前两名是外校的240.220.kx和skyh拿到了190的[暴力打满]的好成绩. 我第5是170分,然而160分就是第19了. 在前一晚上刚刚爆炸完毕后,心态格外平稳. 想想前一天晚上的挣扎: 啊啊啊 ...
- springboot2.0入门(四)----mock模拟测试+单元测试
一.本节主要记录模拟测试.单元测试: 二.mock 测试 1.1什么是Mock? 在面向对象程序设计中,模拟对象(英语:mock object,也译作模仿对象)是以可控的方式模拟真实对象行为的假的对象 ...
随机推荐
- 多个div排列在同一行而不换行
有时候,我们可能会产生多个div标签横向排列而不换行的需求,具体有以下几种实现方法: 1. 同级div设置display:inline-block,父级div强制不换行例如: <html> ...
- Python 入门 之 包
Python 入门 之 包 1.包 (1)什么是包? 文件夹下具有_ init.py _的文件夹就是一个包 (2)包的作用: 管理模块(文件化) (3)包的导入: 导入: 启动文件要和包文件是同级 绝 ...
- node工具之pm2
pm2 PM2是带有内置负载平衡器的Node.js应用程序的生产过程管理器.它使您可以使应用程序永远保持活动状态,无需停机即可重新加载它们,并简化常见的系统管理任务. 安装 npm install p ...
- windows下一步到位搭建pycharm的开发环境
pycharm的开发环境主要涉及到以下三个方面 pycharm的激活 这里采用破解的方式来达到永久激活的目的,因为激活码用着用着就过期的你,会发现不厌其烦的 通过测试,这个破解包适用于2017-201 ...
- python题
1.一行代码实现1--100之和 利用sum()函数求和 sum(range(1,101) 2.如何在一个函数内部修改全局变量 利用global 修改全局变量 3.列出5个python标准库 Pyth ...
- Spring的基本应用(1):IDEA版本
一.Spring概述: 1.什么是Spring? Spring是分层的JavaSE/EE应用full-stack(一站式)轻量级开源框架,以IoC(Inverse Of Control:控制反转)和A ...
- hadoop离线数据存储和挖掘架构
前序: 当你把你知道的东西,写下来,让人看明白是一种境界:当你能把自己写下来的东西给人讲明白,又是另一种境界.在这个过程中,我们都需要历练. 基于hadoop集群下海量离线数据存储和挖掘分析架构: 架 ...
- ubuntu16.04 Installing PHP 7.2
//install sudo add-apt-repository ppa:ondrej/php sudo apt-get update sudo apt-get install php7.2 //C ...
- 惟一ID生成方法
几乎所有的业务系统,都存在生成惟一ID的需求,例如: 用户ID:user_id 订单ID: order_id 消息ID: msg_id 常见的ID生成有三大类方法: 一.中间件实现 1.利用Mysql ...
- 享元模式<Flyweight Pattern>
1.What-是什么? 享元模式是一种轻量级的结构型模式.旨在以共享的方式高效的支持大量的细粒度对象的复用.要求能够共享的对象必须是细粒度对象,这些对象比较相似,状态变化小. 2.Why-为什么? ...