CodeForces 1129C Morse Code
洛谷题目页面传送门 & CodeForces题目页面传送门
题意见洛谷里的翻译。
首先我们可以用区间DP算出对于每个子01串,能表示的字母串的个数。
设\(dp_{i,j}\)表示长度为\(i\),起点为\(j\)(下标从\(1\)开始)的子01串能表示的字母串的个数(也许我设的DP状态有点奇怪)。显然,\(dp_{0,i}=1\),因为空子01串能且仅能表示空字母串。
那么转移怎么转移呢?可以从串的首部转移,从首部挖出\(1\sim4\)个字符组成字母,累加上剩下的串的DP值。那么状态转移方程为\(dp_{i,j}=\sum\limits_{k=1}^{\min(4,i)}dp_{i-k,j+k}\),其中\(k=4\)时还要考虑首部\(4\)个字符是否为不能表示字母的那可怜的\(4\)个01串,如果是的话,就不能累加上\(dp_{i-4,j+4}\)。同样的道理,从尾部转移也是可以的。转移的总时间复杂度是\(\mathrm O\!\left(n^2\right)\),因为一共有\(\mathrm O\!\left(n^2\right)\)个子01串,而每次转移是\(\mathrm{O}(1)\)的。
接下来要算答案了。设到当前第\(i\)次的添加字符后,答案为\(ans\),那么容易想到,下一次(第\(i+1\)次)添加字符后,增加了\([1,i+1],[2,i+1],\cdots,[i+1,i+1]\)这\(i+1\)个子01串,答案变成了\(ans+\sum\limits_{j=1}^{i+1}dp_{i+1-j+1,j}\),我们把\(\sum\limits_{j=1}^{i+1}dp_{i+1-j+1,j}\)累加到\(ans\)里。但是,在累加的过程中,可能对于有的\(j\),\([j,i+1]\)这段子01串和之前累加的有重复,也就是说这段子01串所能表示的所有字母串都被算过了,就不能再把\(dp_{i+1-j+1,j}\)累加上了。所以我们需要判重。
我们可以预处理出前缀哈希数组\(Hsh\),这样可以在\(\mathrm{O}(1)\)时间内计算出任意一个子串的哈希值。然后怎么判重呢?用一个\(vis\)数组肯定不行,因为哈希值在\(\left[0,2^{64}\right)\)内,会MLE。用裸的set
,要判\(\mathrm O\!\left(n^2\right)\)次,每次\(\mathrm O\!\left(\log n^2\right)=\mathrm{O}(\log n)\),总共\(\mathrm O\!\left(n^2\log n\right)\);将set
按子01串长度分成\(n\)组,也还是\(\mathrm O\!\left(n^2\log n\right)\)。这复杂度配上STL的常数,会TLE。
那该怎么办呢?事实上,set
的组数其实应该尽可能多,那样每个set
的元素个数就尽可能少,复杂度就尽可能小。不妨按哈希值模\(10^7\)的值分为\(10^7\)组。这样分,平均每组只有一两个元素,用set
还亏了,直接用链式前向星装即可。
以下是AC代码:
#include<bits/stdc++.h>
using namespace std;
#define N 3000
#define hshmod 10000000//将哈希分为的组数
#define mod 1000000007
#define ull unsigned long long
bitset<N+1> a;//01串
int dp[N+1][N+2];//dp[i][j]表示长度为i,起点为j的子01串能表示的字母串数
inline bool ok(bool a,bool b,bool c,bool d){//是否能表示字母
return !(!a&&!b&&c&&d||!a&&b&&!c&&d||a&&b&&c&&!d||a&&b&&c&&d);//不是那可怜的4个串就OK
}
ull Hsh[N+1]/*前缀哈希值*/,power[N+1]/*power[i]为哈希base(131)的i次方*/;
ull hsh(int l,int r){//[l,r]这段子01串的哈希值
return Hsh[r]-Hsh[l-1]*power[r-l+1];
}
int head[hshmod],nxt[N*N],tot;ull data[N*N];//链式前向星
void add(int x,ull y){//往第x组里添加哈希值y
data[++tot]=y;nxt[tot]=head[x];head[x]=tot;
}
int main(){
int n/*添加字符的次数,即最终01串的长度*/,ans=0/*目前的答案*/,i,j;scanf("%d",&n);
for(i=1;i<=n;i++){int x;scanf("%d",&x);a[i]=x;}
power[0]=1;//131^0=1
for(i=1;i<=n;i++)Hsh[i]=Hsh[i-1]*131ull+a[i]+1,power[i]=power[i-1]*131ull;//预处理
fill(dp[0]+1,dp[0]+n+2,1);//DP边界:dp[i][0]=1
for(i=1;i<=n;i++)for(j=1;j+i-1<=n;j++)//状态转移
dp[i][j]=dp[i-1][j+1],
dp[i][j]+=i>=2?dp[i-2][j+2]:0,dp[i][j]%=mod,
dp[i][j]+=i>=3?dp[i-3][j+3]:0,dp[i][j]%=mod,
dp[i][j]+=i>=4&&ok(a[j],a[j+1],a[j+2],a[j+3])?dp[i-4][j+4]:0,dp[i][j]%=mod;
// for(i=1;i<=n;i++)for(j=1;j+i-1<=n;j++)
// printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
for(i=1;i<=n;i++){//第i次添加字符
for(j=1;j<=i;j++){//枚举新增子01串的左端点,右端点是i
ull h=hsh(j,i);//此新子01串的哈希值
int hmod=h%hshmod;//它的类别
// cout<<h<<" "<<hmod<<" "<<dp[i-j+1][j]<<"\n";
bool mar=false;//是否和之前的某一个串重复
for(int k=head[hmod];k;k=nxt[k])//枚举此组里的元素
if(data[k]==h)//有和它的哈希值相同的?
{mar=true;/*重复*/break;/*不必再找,退出*/}
if(!mar)//如果无重复,照样累加
ans+=dp[i-j+1][j],ans%=mod,add(hmod,h)/*扔进链表*/;
}
printf("%d\n",ans);//输出目前的答案
// puts("");
}
return 0;
}
CodeForces 1129C Morse Code的更多相关文章
- morse code
morse code,摩斯电码,是一种时通时断的信号代码,通过不同的排列顺序来表达不同的英文字母.数字和标点符号. 摩斯电码,是一种早期的数字化通信形式,但是它不同于现代只使用0和1两种状态的二进制代 ...
- 摩尔斯电码(Morse Code)Csharp实现
摩尔斯电码,在早期的"生产斗争"生活中,扮演了很重要的角色,作为一种信息编码标准,摩尔斯电码拥有其他编码方案无法超越的长久生命.摩尔斯电码在海事通讯中被作为国际标准一直使用到199 ...
- Leetcode 804. Unique Morse Code Words 莫尔斯电码重复问题
参考:https://blog.csdn.net/yuweiming70/article/details/79684433 题目描述: International Morse Code defines ...
- [Swift]LeetCode804. 唯一摩尔斯密码词 | Unique Morse Code Words
International Morse Code defines a standard encoding where each letter is mapped to a series of dots ...
- [LeetCode] Unique Morse Code Words 独特的摩斯码单词
International Morse Code defines a standard encoding where each letter is mapped to a series of dots ...
- (string 数组) leetcode 804. Unique Morse Code Words
International Morse Code defines a standard encoding where each letter is mapped to a series of dots ...
- 804. Unique Morse Code Words
Description International Morse Code defines a standard encoding where each letter is mapped to a se ...
- Unique Morse Code Words
Algorithm [leetcode]Unique Morse Code Words https://leetcode.com/problems/unique-morse-code-words/ 1 ...
- LeetCode - 804. Unique Morse Code Words
International Morse Code defines a standard encoding where each letter is mapped to a series of dots ...
随机推荐
- kuangbin专题 专题一 简单搜索 非常可乐 HDU - 1495
题目链接:https://vjudge.net/problem/HDU-1495 题意:有两个空杯(分别是N升和M升)和一罐满的可乐S升,S = N + M,三个容器可以互相倾倒,如果A倒入B,只有两 ...
- 用Supervisor实现进程守护,在异常退出时自动重启
程序启动后,有些是以daemon的形式运行,但在意外退出后,如果不能及时重新启动,会有比较严重的影响. 比如Zimg在图片处理中由于某些图片处理失败,会导致zimg进程挂掉,影响正常的服务提供,并且只 ...
- BI之路学习笔记3--olap cube理解实例
为什么会产生OLAP? 随着数据库技术的发展应用,数据库存储的数据量从M字节以及G(千兆)字节过渡到T字节和P字节,同时,用户的查询需求也越来越复杂,设计的已不仅是查询或者操纵一张关系表中的一条或几条 ...
- CSharp初级篇 1-4 this、索引器、静态、常量以及只读
.NET Core CSharp初级篇 1-4 本节内容为this.索引器.静态.常量以及只读 简介 在之前的课程中,我们谈论过了静态函数和字段的一小部分知识,本节内容中,我们将详细的讲解关于对象操作 ...
- 通过代数,数字,欧几里得平面和分形讨论JavaScript中的函数式编程
本文是对函数式编程范式的系列文章从而拉开了与以下延续一个. 介绍 在JavaScript中,函数只是对象.因此,可以构造函数,作为参数传递,从函数返回或分配给变量.因此,JavaScript具有一流的 ...
- Excel催化剂开源第2波-自动检测Excel的位数选择对应位数的xll文件安装
Excel插件的部署问题难倒了不了的用户,特别是VSTO的部署,用ExcelDna开发的xll文件部署方便,不挑用户机器环境,是其开发Excel插件的一大优势. 其开发出来的xll文件,最终还是需要考 ...
- 人事管理系统为你解剖JSP
人事管理系统为你解剖JSP 前言: 之前写过两篇学习JSP的博客,<Java匹马行天下之JavaWeb核心技术——JSP>https://www.cnblogs.com/zyx110/p/ ...
- c++ 动态规划(数塔)
c++ 动态规划(dp) 题目描述 观察下面的数塔.写一个程序查找从最高点到底部任意位置结束的路径,使路径经过数字的和最大. 每一步可以从当前点走到左下角的点,也可以到达右下角的点. 输入 5 13 ...
- 并发,并行,线程,进程,GIL锁
1.并发和并行 并发: 同时做某些事,但是强调同一时段做多件事 如:同一路口,发生了车辆要同时通过路面的时间. 并行: 互不干扰的在同一时刻做多件事 如:同一时刻,同时有多辆车在多条车道上跑,即同时发 ...
- 物联网时代 跟着Thingsboard学IOT架构-CoAP设备协议
thingsboard官网: https://thingsboard.io/ thingsboard GitHub: https://github.com/thingsboard/thingsboar ...