[ BZOJ 4236 ] JOIOJI

\(\\\)

\(Description\)


给出一个仅由\(J,O,I\)三个字母构成的长度为\(N\)的字符串,定义一段字符串合法,为该字符串三类字符个数相同,求最长合法子串长度。

  • \(N\in [0,2\times 10^5]\)

\(\\\)

\(Solution\)


  • 判断区间和为\(0\)的时候,我们是通过前缀和相同判断的,此题可以参考同样的方法。
  • 注意到有影响区间和是否相同的,是三个字符间的差值,所以记录到每一个位置\(O,I\)分别对\(J\)个数的差,并记录该情况的上一位置即可。注意到状态量最差是\(N^2\)的并开不下,用\(map<pair<int,int>,int>\)就好。

\(\\\)

\(Code\)


#include<map>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 200010
#define R register
#define gc getchar
using namespace std;
 
 
char c;
int n,ans,cnt[3];
map<pair<int,int>,int> m;
 
inline int calc(char c){return (c=='J'?0:(c=='O'?1:2));}
 
int main(){
  c=gc();
  while(!isdigit(c)) c=gc();
  while(isdigit(c)){n=(n<<1)+(n<<3)+(c^48);c=gc();}
  while(!isupper(c)) c=gc();
  ++cnt[calc(c)];
  m[make_pair(0,0)]=0;
  m[make_pair(cnt[1]-cnt[0],cnt[2]-cnt[0])]=1;
  for(R int i=2;i<=n;++i){
    ++cnt[calc(gc())];
    int nowx=cnt[1]-cnt[0];
    int nowy=cnt[2]-cnt[0];
    if(nowx==0&&nowy==0) ans=max(ans,i);
    else{
      if(m[make_pair(nowx,nowy)]!=0) ans=max(ans,i-m[make_pair(nowx,nowy)]);
      else m[make_pair(nowx,nowy)]=i;
    }
  }
  printf("%d\n",ans);
  return 0;
}
posted @ 2018-09-15 16:42  SGCollin  阅读(190)  评论(0编辑  收藏  举报