题目描述

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

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

输入格式

一行由GR组成的字符串

输出格式

最长的稳定的宝石串有多少颗宝石组成

输入输出样例

输入#1                                               输出#1

GRGGRG                                          4

数据范围:

宝石数≤1000000

 

思路:

这道题需要使用前缀和算法。

我们可以使用类似于最长括号匹配(P1944 蓝题)的思想。因为只有GR两种宝石,所以我们可以将字符转化为数字。设G表示的值为1R表示的值为-1,则原来的字符串就变成了一串数字串“1 -1 1 1 -1 1”。这时候,稳定的条件即从‘G'和’R'完全匹配,变成了1和-1相互匹配。

接下来,我们要考虑什么条件能够说明宝石完全匹配。将'G'和'R'转化为1和-1有一个好处:这样如果我们将一个1和一个-1放在一起,组合而成的数的特点即为1+(-1)=0.

这样思考之后,我们就可以维护这个数字串的前缀和数组:1 0 1 2 1 2。当在前缀和数组中,两个数的值相等,则说明宝石已经完全匹配。

这样我们就有了写代码的思路:建立一个数组f,f[i]表示从第i块宝石往前推,所构成的稳定的宝石串的最大长度。而计算整个宝石串内稳定的串的最大长度,只需要对f数组取max即可。

下面是代码:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 string s;
 5 int n,i,j,ans;
 6 int sum[1000005]={0},f[1000005]={0};
 7 int main(){
 8     cin>>s;
 9     n=s.length();
10     for(i=1;i<=n;i++){
11         if(s[i-1]=='G'){ //绿宝石代表1
12             sum[i]=sum[i-1]+1;
13         }else if(s[i-1]=='R'){ //红宝石代表-1
14             sum[i]=sum[i-1]-1;
15         }
16     }
17     ans=-99999;
18     for(i=1;i<=n;i++) {
19         for(j=i;j>=1;j--) {
20             if(sum[i]==sum[j]) {
21                 f[i]=i-j;
22             }
23         }
24         if(ans<f[i]){
25             ans=f[i];
26         }
27     }
28     cout<<ans<<endl;
29     return 0;
30 }

但是这份代码只能得40分。

为什么?

这份代码的问题在于它枚举的边界出现了错误

我们来考虑,当数据为GGRRGR的时候,得到的对应的前缀和数组为:1 2 1 0 1 0.这样我们在运行程序的时候,得到的结果是4.但是,事实上,正确的答案很明显应该是6.这是为何呢?

我们再一次看这份代码:

这份代码的问题出在:我们的前缀和数组是从1开始维护的。但是我们并没有考虑这样一种情况:当我们的真实最长稳定序列是从头开始的时候,我们判断这个序列是否稳定应该依据于这个序列的尾结点sum值是否等于0.然而我们并没有存储这个‘0’,所以这种情况就被略过了。

那么这个问题如何解决呢?只需要将sum[0]=0加入到枚举的范围中即可。

下面是AC代码:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 string s;
 5 int n,i,j,ans;
 6 int sum[1000005]= {0},f[1000005]= {0};
 7 int main() {
 8     cin>>s;
 9     n=s.length();
10     for(i=1; i<=n; i++) {
11         if(s[i-1]=='G') { //绿宝石代表1
12             sum[i]=sum[i-1]+1;
13         } else if(s[i-1]=='R') { //红宝石代表-1
14             sum[i]=sum[i-1]-1;
15         }
16     }
17     ans=-99999;
18     for(i=1; i<=n; i++) {
19         for(j=i; j>=0; j--) {//枚举到0
20             if(sum[i]==sum[j]) {
21                 f[i]=i-j;
22             }
23         }
24         if(ans<f[i]) {
25             ans=f[i];
26         }
27     }
28     cout<<ans<<endl;
29     return 0;
30 }

 

posted on 2020-07-18 07:58  郭谦  阅读(459)  评论(0编辑  收藏  举报