BZOJ 4236: JOIOJI MAP
4236: JOIOJI
Time Limit: 1 Sec
Memory Limit: 256 MB
题目连接
http://www.lydsy.com/JudgeOnline/problem.php?id=4236Description
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<=2*10^5
题意
题解:
我们用前缀和的东西统计到这个位置一共有多少个J,O,I。
假设A[i],B[i],C[i]表示前i个位置分别有多少个J,O,I。
那么只要找到一队A[j]-B[j]==A[i]-B[i],而且B[j]-C[j]==B[j]-C[j]就好了
化简之后就是A[j]-A[i]=B[j]-B[i],B[j]-B[i]=C[j]-C[i]
用一个MAP来维护一下就好了
代码:
//qscqesze #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <bitset> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 204051 #define mod 10007 #define eps 1e-9 int Num; //const int inf=0x7fffffff; //§ß§é§à§é¨f§³ const int inf=0x3f3f3f3f; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } //************************************************************************************** char s[maxn]; map<pair<int,int> ,int> H; int ans=0; int A,B,C; int main() { int n=read(); scanf("%s",s+1); H[make_pair(0,0)]=0; for(int i=1;i<=n;i++) { if(s[i]=='J') A++; if(s[i]=='O') B++; if(s[i]=='I') C++; if(H.find(make_pair(A-B,B-C))==H.end()) H[make_pair(A-B,B-C)]=i; else ans = max(ans,i-H[make_pair(A-B,B-C)]); } printf("%d\n",ans); }