题目描述
有一种宝石串,由绿宝石和红宝石串成,仅当绿宝石和红宝石数目相同的时候,宝石串才最为稳定,不易断裂。安安想知道从给定的宝石串中,可以截取一段最长的稳定的宝石串,有多少颗宝石组成。请你帮助他。
绿宝石用‘G’表示,红宝石用‘R'表示。
输入格式
一行由G和R组成的字符串
输出格式
最长的稳定的宝石串有多少颗宝石组成
输入输出样例
输入
GRGGRG输出
4说明/提示
RGGR为答案。
宝石数<=1000000
这道题我看到标签是前缀和
我一开始到草稿纸上分别去列G和R个数的前缀和,发现没什么软用。
然后我就设定遇到’G‘,sum【i】=sum【i-1】+1;
遇到’R‘,sum【i】=sum【i-1】-1;
来求前缀和。
接着我就想从sum数组两端往中间取第一对相等的值,那么他们的坐标差就是最长序列长度。
然后我就不知道该怎么求...emmmm。
然后呢 算法组的小伙伴提示我线性求解。
于是我设置跨度从0到L(字符串的长度)递增循环,每次规定好求的相等值,然后再去找前后第一个,算差值然后去更新最长长度。
然后有两个小细节害我两次没AC。
一个是:因为我的前缀和数组是从1开始记录的,但是字符串的下标是从0开始的,所以推算前缀和序列的时候字符串下标一定要记得 i-1。(这种错误断点判断很容易发现)
二一个是 :sum【0】时没有字符,所以sum【0】=0,当跨度为0时,只需要从后往前遍历找第一个sum【i】为0的值,它的下标是第一个最大长度。然后再从1的跨度开始寻找。
修改好了这两个点,题目就做出来啦!
AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,a[10000001],l,mxa,s1,s2;
string s;
int main()
{
cin>>s;
l=s.size();
for(int i=1; i<=l; i++)
if(s[i-1]=='G')a[i]=a[i-1]+1;
else a[i]=a[i-1]-1;
for(int j=l; j>=1; j--){
if(a[j]==0){
mxa=j;
break;
}
}
for(int i=1; i<=l; i++)
{
//向上跨
for(int j=1; j<=l; j++){
if(a[j]==i){
s1=j;
break;
}
}
for(int j=l; j>=1; j--){
if(a[j]==i){
s2=j;
break;
}
}
mxa=max(mxa,s2-s1);
//向下跨
for(int j=1; j<=l; j++){
if(a[j]==-1*i){
s1=j;
break;
}
}
for(int j=l; j>=1; j--){
if(a[j]==-1*i){
s2=j;
break;
}
}
mxa=max(mxa,s2-s1);
}
cout<<mxa;
return 0;
}