luogu P2697 宝石串

来源:互联网 发布:百图水利软件 编辑:程序博客网 时间:2024/05/16 10:17

题目描述

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

绿宝石用‘G’表示,红宝石用‘R’表示。

输入输出格式

输入格式:
一行由G和R组成的字符串

输出格式:
最长的稳定的宝石串有多少颗宝石组成

输入输出样例

输入样例#1:

GRGGRG

输出样例#1:

4

说明

RGGR为答案。

宝石数<=1000000


这道题看数据范围不是O(n)就是O(nlogn),所以我们可以从数据范围入手,显然我们一般会从O(nlogn)这个复杂度分析;

O(nlogn)(WA):

显然我们可以从二分入手,这样子复杂度是O(nlogn)的,那我们会枚举答案长度,然后进行二分,然后就会处理细节,比如为了好处理,我们会让’G’记为1,’R’记为0,这样我们处理可以用^来快速处理颜色,但是打完会发现WA,那我们就要反思一下,为什么这个算法会WA;

因为这个题目不满足二分的性质,所以不行,但是在反思中,我们会发现“我们会让’G’记为1,’R’记为0”这步处理,所以,我们可以想到一个别的方法来处理:’G’还是1,但’R’是-1,这样如果有一段区间的’G”R’数量相等,那么这段区间的和为0;

所以,正确的算法是乱搞,复杂度是O(n);

O(n)(正解):

我们输入时处理好1和-1,然后用一个for循环来记录前缀和s,如果当前出现的前缀s和已经在此之前出现过,则说明从之前出现这个前缀和s的位置到现在这个位置中间的’G’和’R’的数量是相等的,所以这时候我们更新一下答案ans,最后输出ans就好了;当然,如果前缀和s第一次出现,我们需要记录下位置;


完整代码:

#include<iostream>#include<cstdio>#define mid ((l+r)>>1)#define II int#define R register#define I 2000010using namespace std;II wei[I],a[I];II n,ans;int main(){    R char p; R II now=0;    while (scanf("%c",&p)!=EOF&&p!='\n') p=='G'? a[++n]=1: a[++n]=-1;        //'G' is 1,'R' is -1;    a[n+1]=n+n+25;    a[n+2]=n+n+54;    a[n+3]=n+n+46;        //这里可有可无;    for(R II i=0;i<=n*2+12;i++) wei[i]=-1;        //初始化每个点第一次出现的位置;    wei[1]=0;wei[1+n]=0;        //0第一次出现的位置是0,即没有宝石的时候;    for(R II i=1;i<=n;i++)    {        now+=a[i];        if(wei[now+n+1]==-1) wei[now+n+1]=i;          else ans=max(ans,i-wei[now+n+1]);    }    printf("%d\n",ans);    return 0;}

by pretend-fal;

END;

原创粉丝点击