• 【bzoj4236】JOIOJI STL-map


    题目描述

    JOIOJI桑是JOI君的叔叔。“JOIOJI”这个名字是由“J、O、I”三个字母各两个构成的。
    最近,JOIOJI桑有了一个孩子。JOIOJI桑想让自己孩子的名字和自己一样由“J、O、I”三个字母构成,并且想让“J、O、I”三个字母的出现次数恰好相同。
    JOIOJI桑家有一份祖传的卷轴,上面写着一首长诗,长度为N,由“J、O、I”三个字母组成。JOIOJIさん想用诗中最长的满足要求的连续子串作为孩子的名字。
    现在JOIOJI桑将这首长诗交给了你,请你求出诗中最长的、包含同样数目的“J、O、I”三个字母的连续子串。

    输入

    第一行一个正整数N,代表这首长诗的长度
    接下来一行一个长度为N的字符串S,表示这首长诗,保证每个字符都是“J、O、I”三个字母中的一个

    输出

    输出一行一个正整数,代表最长的包含等数量“J、O、I”三个字母的最长连续子串的长度。如果不存在这样的子串,输出0

    样例输入

    10
    JOIIJOJOOI

    样例输出

    6


    题解

    STL-map

    设a[i]为1~i中'J'的个数,b[i]为1~i中'O'的个数,c[i]为1~i中'I'的个数。

    那么如果[i+1,j]区间可被选择,一定有a[j]-a[i]==b[j]-b[i]==c[j]-c[i],

    即a[j]-b[j]==a[i]-b[i],a[j]-c[j]==a[i]-c[i]。

    根据这个我们可以把a[i]-b[i]和a[i]-c[i]存起来,再从左向右找,如果找到就用j-i更新答案,没找到则扔到map里。

    理论时间复杂度O(nlogn),实际会更快一些。

    考场上懵逼了,写了CDQ分治,效率稍微低了一些,反正就当练手了。

    #include <cstdio>
    #include <map>
    #include <utility>
    using namespace std;
    map<pair<int , int> , int> v;
    char str[200010];
    int main()
    {
    	int n , i , ans = 0 , a = 0 , b = 0;
    	scanf("%d%s" , &n , str + 1);
    	v[make_pair(0 , 0)] = 0;
    	for(i = 1 ; i <= n ; i ++ )
    	{
    		if(str[i] == 'J') a ++ , b ++ ;
    		if(str[i] == 'O') a -- ;
    		if(str[i] == 'I') b -- ;
    		if(v.find(make_pair(a , b)) == v.end()) v[make_pair(a , b)] = i;
    		else ans = max(ans , i - v[make_pair(a , b)]);
    	}
    	printf("%d
    " , ans);
    	return 0;
    }
  • 相关阅读:
    java小白学习练手成绩管理系统(一)
    java初级学习练手成绩管理系统(四)
    Echart可视化学习集合
    java小白学习练手成绩管理系统(六)
    java小白学习练手成绩管理系统
    网页内容加密
    Ubuntu 10.04 安装配置指南
    Linux目录解释
    完整清除XP垃圾文件系统自带的秘密武器
    人人都应该掌握的一些电脑操作技巧
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6616996.html
Copyright © 2020-2023  润新知