前缀和(P2697 宝石串)
前言
每次做出来什么本来做不出的题目,就忍不住记录一下。不过大多时候隔几天来看,就发现,啊,我当时只是做了一道这么弱智的题目呀,哈哈。前缀和确实不算太难。。
传送门
题目大意:
给你一个字符串只含G和R,求一个最长子串长度,使得两个字符的长度相等。(给的字符串长小于1e6)
如:GRGGRG
答案是:4。
思路
题目中字符串很长,暴力枚举显然不可能。
但我们仔细一看,发现不过只有两个字符G和H。我们令G为1,令R为-1,那么GR的值就为0,这显然是一个可行的子串。
那再看GRGGRG,我们开一个a数组记录前i个字符的值,那么
a[0]=0,a[1]=1,a[2]=0,a[3]=1.a[4]=2,a[5]=1,a[6]=2。
观察可得1~3是一个可行的子串(不包括1)
1~5同样可行(不包括1)
也就是说,当他们对应的a数组值相等时,中间的串必定可行,因为中间的串没有引起值的变化,那么G和R相等。
那接下来我们该怎么做呢?
我们可以用2个for循环枚举数组a,找出值相等并且下标相差最大的两个点即为最大子串,但这样复杂度过高。
O(n)做法
我们以DP的角度考虑一个优解,使得这个过程能在线性时间内完成。如对于可行的长度为2的子串,我们只需要记录出现最早的长度为2的下标和出现最晚的下标即可。这里结合代码理解:
for(int i=0;i<str1.length();i++)
{
if(str1[i]=='G')
a[i+1]=a[i]+1;//计算a数组的值
else
a[i+1]=a[i]-1;
dp[a[i+1][1]=min(dp[a[i+1]][1],i+1);//记录最早
dp[a[i+1]][2]=max(dp[a[i+1]][2],i+1);//记录最晚
}
但是新的问题又来了,a[i+1]可能是负数,数组可没有负数的下标!其实这并不难,我们把dp的第一维扩大一倍,把中间的下标当作原来的下标零来使用,像这样:
//maxn=10000007
for(int i=0;i<str1.length();i++)
{
if(str1[i]=='G')
a[i+1]=a[i]+1;
else
a[i+1]=a[i]-1;
dp[a[i+1]+maxn+1][1]=min(dp[a[i+1]+maxn+1][1],i+1);
dp[a[i+1]+maxn+1][2]=max(dp[a[i+1]+maxn+1][2],i+1);
}
完整代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1000009;
int a[2*maxn];
string str1;
int dp[maxn*2+9][3];
int main()
{
cin>>str1;
for(int i=0;i<=maxn*2-5;i++)
dp[i][1]=100000000;//为min作预处理
dp[maxn+1][1]=0;//这里可以把maxn+1看作原来的下标0
for(int i=0;i<str1.length();i++)
{
if(str1[i]=='G')
a[i+1]=a[i]+1;
else
a[i+1]=a[i]-1;
dp[a[i+1]+maxn+1][1]=min(dp[a[i+1]+maxn+1][1],i+1);
dp[a[i+1]+maxn+1][2]=max(dp[a[i+1]+maxn+1][2],i+1);
}
int sumn=0;
for(int i=0;i<=maxn+str1.length();i++)//注意,从下标0开始
sumn=max(sumn,dp[i][2]-dp[i][1]);
cout<<sumn;
}
感谢dalao过目!
前缀和(P2697 宝石串)的更多相关文章
- Luogu P1114 “非常男女”计划/Luogu P2697 宝石串
Luogu P1114 "非常男女"计划/Luogu P2697 宝石串 (感觉我最近很爱做双倍经验的题啊) 使$d$等于第$i$个位置男生数(绿宝石数)减女生数(红宝石数)的差值 ...
- 洛谷 P2697 宝石串
题目传送门 解题思路: 将红色的设置为-1,绿色的为1,统计前缀和sum,如果sum[i] == sum[j],则说明i~j是一个稳定的区间 因为答案要求最大,所以我们要记录每个sum值的最左端点(也 ...
- HDU 1358 (所有前缀中的周期串) Period
题意: 给出一个字符串,在所有长度大于1的前缀中,求所有的周期至少为2的周期串,并输出一个周期的长度以及周期的次数. 分析: 有了上一题 HDU 3746 的铺垫,这道题就很容易解决了 把next求出 ...
- HDU 6153 A Secret 套路,求解前缀在本串中出现的次数
http://acm.hdu.edu.cn/showproblem.php?pid=6153 首先相当于翻转两个串,然后求s2前缀在s1中出现的次数. 这是一个套路啦 首先把两个串结合起来,中间加一个 ...
- Simpsons’ Hidden Talents - HDU 2594(求相同的前缀后缀)
题目大意:给你两个字符串,找出一个最大的子串,这个子串要是前面串的前缀并且是后面串的后缀........... 分析:next的简单运用吧,可以把两个串进行合并,中间加一个不能被匹配的字符,然后求 ...
- 2015 UESTC Training for Search Algorithm & String - M - Palindromic String【Manacher回文串】
O(n)的复杂度求回文串:Manacher算法 定义一个回文值,字符串S是K重回文串,当且仅当S是回文串,且其长度为⌊N/2⌋的前缀和长度为⌊N/2⌋的后缀是K−1重回文串 现在给一个2*10^6长度 ...
- 「BZOJ 4502」串
「BZOJ 4502」串 题目描述 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合 \(S\),然后它们定义一个字符串为"好"的,当且仅当它可以被分成非空的两段,其中每一段 ...
- hdu3336 KMP + DP 前缀数组出现的次数
题意: 给你一个串,问你他的所有前缀子串在本串中的出现次数,注释:abc的前缀子串是 a ab abc; 思路: 还是利用了next数组,先对子串求出next数组,再开一个数组d ...
- [51nod1587]半现串
将s所有长度为d/2的子串放进ac自动机中,直接匹配就可以判定半现串了再对其做一个差分,询问一个前缀的半现串个数,在ac自动机上数位dp,f[i][j][0/1]表示走了i步(i位的字符串),走到节点 ...
随机推荐
- mysql报错: unknown variable 'sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES'
在修改mysql默认字符集的时候: 1. 需要拷贝/usr/share/mysql下的my-huge.cnf 或者my-small.cnf到 /etc/my.cnf,但是官网说:从5.7.18开始不在 ...
- Redis之quicklist源码分析
一.quicklist简介 Redis列表是简单的字符串列表,按照插入顺序排序.你可以添加一个元素到列表的头部(左边)或者尾部(右边). 一个列表最多可以包含 232 - 1 个元素 (4294967 ...
- Redis之事务操作
1.Redis事务的概念: Redis 事务的本质是一组命令的集合.事务支持一次执行多个命令,一个事务中所有命令都会被序列化.在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求 ...
- 利用numpy实现多维数组操作图片
1.上次介绍了一点点numpy的操作,今天我们来介绍它如何用多维数组操作图片,这之前我们要了解一下色彩是由blue ,green ,red 三种颜色混合而成,0:表示黑色 ,127:灰色 ,255:白 ...
- Leetcode802-找到最终的安全状态(Python3)
刚开始没思路,还以为是利用二维矩阵直接标记节点间的有向路径,最后循环遍历就能得到结果,结果最后发现方向是错的,之后看了大佬们写的代码,发现原来是用出度来实现节点是否安全的. 照着大佬们的思路重新写了一 ...
- Atcoder E - Crested Ibis vs Monster、
一看到题目就觉得是一个背包问题,但是不知道怎么写. 题解:直接求背包容量为2*h时所需要的花费.然后h~2h都是满足条件的,去最小值即可. code: #include<bits/stdc++. ...
- Xshell 设置右键粘贴即是复制
打开工具->选项->键盘和鼠标面板 1.鼠标部分的右击设置"粘贴剪切板的内容". 2.选择部分,在"自动将所选文本复制到剪切板"前打勾
- PHP函数:array_chunk
array_chunk() - 将一个数组分割成多个. 说明: array_chunk ( array $array , int $size [, bool $preserve_keys = fa ...
- [GitHub] 75+的 C# 数据结构和算法实现
C#中标准数据结构和算法的即插即用类库项目 GitHub:https://github.com/aalhour/C-Sharp-Algorithms Watch: 307 Star: 3.4k For ...
- hadoop 伪分布配置
配置 Hadoop 伪分布式 任务配置说明: VMware 15 Centos 6.5 java -jdk 1.8 hadoop-2.6.0-cdh5.14.0.tar.gz 第一步 自行安装虚拟机 ...