1. 程式人生 > >BZOJ4236 JOIOJI 【map】

BZOJ4236 JOIOJI 【map】

BZOJ4236 JOIOJI

Description

JOIOJI桑是JOI君的叔叔。“JOIOJI”這個名字是由“J、O、I”三個字母各兩個構成的。
最近,JOIOJI桑有了一個孩子。JOIOJI桑想讓自己孩子的名字和自己一樣由“J、O、I”三個字母構成,並且想讓“J、O、I”三個字母的出現次數恰好相同。
JOIOJI桑家有一份祖傳的卷軸,上面寫著一首長詩,長度為N,由“J、O、I”三個字母組成。JOIOJIさん想用詩中最長的滿足要求的連續子串作為孩子的名字。
現在JOIOJI桑將這首長詩交給了你,請你求出詩中最長的、包含同樣數目的“J、O、I”三個字母的連續子串。

Input

第一行一個正整數N,代表這首長詩的長度
接下來一行一個長度為N的字串S,表示這首長詩,保證每個字元都是“J、O、I”三個字母中的一個

Output

輸出一行一個正整數,代表最長的包含等數量“J、O、I”三個字母的最長連續子串的長度。如果不存在這樣的子串,輸出0

Sample Input

10
JOIIJOJOOI

Sample Output

6

HINT

選擇“IIJOJO”這個子串,長度為6,包含“J、O、I”三個字母各2個,這是最長的滿足要求的子串。
1<=N<=21052*10^5

我們考慮怎麼快速判斷兩個位置作差後JOI的數量相等
Ji=JiJ_i=J_i,Oi=OjO_i=O_j,Ii=IiI_i=I_i
JiOi=JjOj,OiIi=OjIjJ_i-O_i=J_j-O_j,O_i-I_i=O_j-I_j


然後我們就可以用map來壓縮每一個位置的值

然後就做完了

注意第0個位置也存在

#include<bits/stdc++.h>
using namespace std;
#define N 200010
#define fu(a,b,c) for(int a=b;a<=c;a++)
#define fd(a,b,c) for(int a=b;a>=c;a--)
#define pi pair<int,int>
int J=0,O=0,I=0,n;
pi p[N];
char c[N];
map<pi,int
> mp; int main(){ scanf("%d%s",&n,c+1); mp[pi(0,0)]=0; fu(i,1,n){ if(c[i]=='J')J++; if(c[i]=='O')O++; if(c[i]=='I')I++; p[i]=pi(I-O,O-J); if(!mp.count(p[i]))mp[p[i]]=i; } int ans=0; fd(i,n,1)ans=max(ans,i-mp[p[i]]); printf("%d",ans); return 0; }