前言

每次做出来什么本来做不出的题目,就忍不住记录一下。不过大多时候隔几天来看,就发现,啊,我当时只是做了一道这么弱智的题目呀,哈哈。前缀和确实不算太难。。

传送门

题目大意

给你一个字符串只含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 宝石串)的更多相关文章

  1. Luogu P1114 “非常男女”计划/Luogu P2697 宝石串

    Luogu P1114 "非常男女"计划/Luogu P2697 宝石串 (感觉我最近很爱做双倍经验的题啊) 使$d$等于第$i$个位置男生数(绿宝石数)减女生数(红宝石数)的差值 ...

  2. 洛谷 P2697 宝石串

    题目传送门 解题思路: 将红色的设置为-1,绿色的为1,统计前缀和sum,如果sum[i] == sum[j],则说明i~j是一个稳定的区间 因为答案要求最大,所以我们要记录每个sum值的最左端点(也 ...

  3. HDU 1358 (所有前缀中的周期串) Period

    题意: 给出一个字符串,在所有长度大于1的前缀中,求所有的周期至少为2的周期串,并输出一个周期的长度以及周期的次数. 分析: 有了上一题 HDU 3746 的铺垫,这道题就很容易解决了 把next求出 ...

  4. HDU 6153 A Secret 套路,求解前缀在本串中出现的次数

    http://acm.hdu.edu.cn/showproblem.php?pid=6153 首先相当于翻转两个串,然后求s2前缀在s1中出现的次数. 这是一个套路啦 首先把两个串结合起来,中间加一个 ...

  5. Simpsons’ Hidden Talents - HDU 2594(求相同的前缀后缀)

    题目大意:给你两个字符串,找出一个最大的子串,这个子串要是前面串的前缀并且是后面串的后缀...........   分析:next的简单运用吧,可以把两个串进行合并,中间加一个不能被匹配的字符,然后求 ...

  6. 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长度 ...

  7. 「BZOJ 4502」串

    「BZOJ 4502」串 题目描述 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合 \(S\),然后它们定义一个字符串为"好"的,当且仅当它可以被分成非空的两段,其中每一段 ...

  8. hdu3336 KMP + DP 前缀数组出现的次数

    题意:       给你一个串,问你他的所有前缀子串在本串中的出现次数,注释:abc的前缀子串是 a ab abc; 思路:      还是利用了next数组,先对子串求出next数组,再开一个数组d ...

  9. [51nod1587]半现串

    将s所有长度为d/2的子串放进ac自动机中,直接匹配就可以判定半现串了再对其做一个差分,询问一个前缀的半现串个数,在ac自动机上数位dp,f[i][j][0/1]表示走了i步(i位的字符串),走到节点 ...

随机推荐

  1. web.page.regexp用法(全网唯一)

    前言 因为这个东西“web.page.regexp”,差点把自己杀了.一点都不夸张,这将近30度的天气,办公室不开空调,又要闷,还要带着口罩,躁动的很.加上这个鬼东西“web.page.regexp” ...

  2. N皇后问题 回溯非递归算法 C++实现2

    运行结果 代码如下 #include <bits/stdc++.h> using namespace std; ; const char *LINE32 = "--------- ...

  3. 移动硬盘临时文件太多怎么办,python黑科技帮你解决

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 星安果 PS:如果想了解更多关于python的应用,可以私信我,或者 ...

  4. 【JAVA】并发-基础IO

    一.java.io包支持.java的IO流有输入.输出两种,每种输入.输出流又可分为字节流.字符流两大类,字节流以字节为单位处理IO操作,字符流以字符为单位处理IO操作 JDK 1.4以后有java. ...

  5. ubuntu-18.0.4 samba安装

    (1)安装 sudo apt-get -y install samba samba-common (2)创建一个用于分享的samba目录. mkdir /home/myshare (3)给创建的这个目 ...

  6. Aria2任意文件写入漏洞

    目录: 简介 漏洞描述 payload 漏洞复现 一.Aria2介绍 Aria2是一个命令行下运行,多协议,多来源下载工具(HTTP / HTTPS,FTP,BitTorrent,Metalink), ...

  7. pytorch 孪生神经网络DNN

    代码内容请见: https://github.com/LiuXinyu12378/DNN-network

  8. 有关HTTP协议

    有关HTTP协议:https://www.cnblogs.com/an-wen/p/11180076.html

  9. 2019-2020-1 20199325《Linux内核原理与分析》第二周作业

    冯诺依曼计算机硬件框图: 下面是一个简单的程序example.c. intadd_a_and_b(int a,int b){returna+b;}intmain(){returnadd_a_and_b ...

  10. (转)SQLite数据库的加密

    1.创建空的SQLite数据库. //数据库名的后缀你可以直接指定,甚至没有后缀都可以 //方法一:创建一个空sqlite数据库,用IO的方式 FileStream fs = File.Create( ...