P2697 宝石串
思路
将'G'看成\(-1\),'R'看成\(+1\),要求最长的子串,使得子串中‘G’和‘R'的数量相等,则转化为求两个下标\(i\)和\(j\),使得前缀和\(sum[j]-sum[i-1]=0\),即\(sum[j] == sum[i-1]\)。
开一个\(pos\)数组记录每个\(sum[i]\)第一次出现的位置,之后对每个位置\(i\),如果\(sum[i]\)未出现过,则将\(sum[i]\)的位置记为\(i\),否则说明\(sum[i]\)出现过,更新答案。(为什么记录第一次?保证最长子串!)
注意点
\(0\)第一次出现的位置为下标\(0\),这是由于前缀和数组中\(sum[0]=0\)。
const int N=1e6+10;
char s[N];
int pos[N<<1];
int n;
int main()
{
memset(pos,-1,sizeof pos);
scanf("%s",s+1);
int n=strlen(s+1);
int sum=0,res=0;
pos[0+n]=0;
for(int i=1;i<=n;i++)
{
if(s[i] == 'G') sum--;
else sum++;
if(pos[sum+n] == -1)
pos[sum+n]=i;
else
res=max(res,i-pos[sum+n]);
}
cout<<res<<endl;
//system("pause");
return 0;
}