AT1224 JOIOJI

题面

JOIOJI桑是JOI君的叔叔。“JOIOJI”这个名字是由“J、O、I”三个字母各两个构成的。

最近,JOIOJI桑有了一个孩子。JOIOJI桑想让自己孩子的名字和自己一样由“J、O、I”三个字母构成,并且想让“J、O、I”三个字母的出现次数恰好相同 。

JOIOJI桑家有一份祖传的卷轴,上面写着一首长诗,长度为 \(N\),由“J、O、I”三个字母组成。JOIOJIさん想用诗中最长的满足要求的连续子串作为孩子的名字。

现在JOIOJI桑将这首长诗交给了你,请你求出诗中最长的、包含同样数目的“J、O、I”三个字母的连续子串的长度。

简化题意

有一个由 JOI 组成的字符串,求一个子串,使得这三个字符出现次数一样。输出子串的长度的最大值。

思路

本题可以用一个前缀和来维护。

\(J=1,O=1145141,I=-1145142\),那么就转换成了一个最长的和为 \(0\) 的子串。(之所以取 \(1145141\),是应为这个数比较大)。

枚举 \(i\ (\text{from } 1 \text{ to } n)\)。如果当前子串 \([1,i]\) 的和是 \(0\),那么更新答案。然后就判断存储器中有没有答案,如果有,更新,否则就记录当前和。

至于存储器,可以使用 std::map 实现。

时间复杂度为 \(O(n\log n)\)

#include <bits/stdc++.h>
#define int long long
using namespace std;

int n;
char poem[200005];
int qzh,result=0;
map<int,int> mem;

signed main(){
	cin>>n;
	cin>>(poem+1);
	for(int i=1;i<=n;i++){
		char nch=poem[i];
		switch(nch){
			case 'J':
				qzh++;
				break;
			case 'O':
				qzh+=1145141;
				break;
			case 'I':
				qzh+=(-1145141-1);
				break;
		}
		if(qzh==0){
			result=max(result,i);
		}
		if(mem[qzh]!=0){
			result=max(result,i-mem[qzh]);
		}
        else {
        	mem[qzh]=i;	
		}
	}
	cout<<result<<endl;
	return 0; 
}
posted @ 2022-03-19 16:37  蒟蒻xiezheyuan  阅读(40)  评论(0编辑  收藏  举报