P2697 宝石串

106 阅读1分钟

题目描述

有一种宝石串,由绿宝石和红宝石串成,仅当绿宝石和红宝石数目相同的时候,宝石串才最为稳定,不易断裂。安安想知道从给定的宝石串中,可以截取一段最长的稳定的宝石串,有多少颗宝石组成。请你帮助他。

绿宝石用‘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;
}