Problem L. ZZUPC

本来以为是三月末甚至四月初才面试,所以当时学弟找我打校赛我就答应了(我说小概率时间可能会冲突,他说没事还有另一个大爹然后发现是我队友,没绷住 )。结果校赛时间定在21号,我20号晚上收到的面试通知,要我24号就面试,没招了。不过不是硬性冲突,就当是给机试练练手,所以我就还是上了。

这场赛时做起来不太顺,可能是太长时间没打所以手比较生。反正罚时吃的比较多,最后憋了两道题也没憋出来,才弄了个校第二,没招了。其实好像也不冤,毕竟我们队俩主力,还一年没认真训练了,而大三学弟队是经过大二一整年心无旁骛的训练的,所以水平没准比我们还强不少。不过就算同时期,也肯定是比不过我们的学长他们了,我刚入学那会真是看神仙打架,现在学长们都走了,哎感慨万千。

今天刚回,趁着还有点记忆说说 L 题,这题真不难,放大二的时候我们队估计直接秒了,气的我队友(还有一个在出题组,当天在当志愿者)指着我俩鼻子骂:"你们忘本了知不知道?"(他说这是当时我们进实验室那场选拔赛的题,但是我真没啥记忆了)。


Problem L. ZZUPC

  • Input file: standard input
  • Output file: standard output
  • Time limit: 2 second
  • Memory limit: 256 mebibytes

Zerc 在「浪潮杯」郑州大学第 17 届大学生程序设计竞赛 / The 17th ZZUPC 开始前向服务器祈祷。

突然,屏幕上出现了一个长度为 nnn 的仅由大写英文字母 Z U C P 组成的字符串 SSS。

下面还有一行文字:If you can find the maximum length of the lucky string, then I can bless this competition to go smoothly.

定义字符串 TTT 为幸运字符串 ,当且仅当:TTT 的字符可以通过重新排列,变成 (ZZUPC)×k(ZZUPC) \times k(ZZUPC)×k(即 kkk 个 ZZUPC 字符串首尾拼接而成,kkk 为非负整数)。

例如:

  • ZZUPC 是幸运字符串(k=1k=1k=1);
  • ZZUPCPCZZUPC 是幸运字符串(k=2k=2k=2);
  • ZUPCPCZ 可以重新排列为 ZZUPC,因此也是幸运字符串(k=1k=1k=1);
  • ZZUCP 无法重新排列为 ZZUPC × k,因此不是幸运字符串。

现在给定字符串 SSS,请你求出 SSS 的所有子串中,最长的幸运字符串的长度。

子串 (Substring) :若字符串 ttt 可以表示为 sss 中一段连续的字符序列,则称 ttt 是 sss 的子串。

形式化地,若存在 1≤l≤r≤∣s∣1 \le l \le r \le |s|1≤l≤r≤∣s∣,使得 t=slsl+1...srt = s_l s_{l+1} \dots s_rt=slsl+1...sr,则 ttt 是 sss 的子串。

例如:s=abcdes = abcdes=abcde,则 bcdade 均为其子串。而 ae 不是其子串。


Input

第一行输入一个整数 TTT (1≤T≤51 \le T \le 51≤T≤5),表示测试用例的数量。

对于每组测试样例:

  • 第一行一个整数 nnn (1≤n≤2×1051 \le n \le 2 \times 10^51≤n≤2×105),代表字符串长度;
  • 第二行一个长度为 nnn 的字符串 SSS,且仅包含字符 Z、U、C、P。

Output

对于每个测试用例,输出一个整数,表示最长的幸运字符串的长度。


Examples

输入1

cpp 复制代码
3
6
ZZUPC
8
ZZZUUCCP
13
ZZZZZUCPCUCPC

输出1

cpp 复制代码
6
0
12 

Note

  • 第一个测试用例:字符串本身就是 ZZUPC,长度为 6,对应 k=1k=1k=1。
  • 第二个测试用例:不包含幸运字符串。
  • 第三个测试用例:第 2 到 13 字符可以通过重组得到 ZZUPCPCZZUPC,故幸运字符串的最大长度为 12。

思路:

一开始的思路是:枚举最长的幸运字符串长度,对每种字符枚举右端点,找左端点的位置区间,然后四种字符的合法区间取交集。但是这个幸运字符串长度是不满足单调性的(即存在长的幸运字符串,不一定存在短的幸运字符串),因此无法二分答案。这样无论如何都无法做到低于 O(n2)O(n^2)O(n2) 的时间复杂度,何况还要找四种字符的左端点位置区间的交集。

正解是这样的:对一个长为 6k6k6k 的幸运字符串,它有 2k2k2k 个 Z, kkk 个 U, kkk 个 P, 2k2k2k 个 C。不妨先看 UP如果我们边处理边存储 前缀中 P 减去 U 的个数,那么我们就可以在 O(n)O(n)O(n) 的时间,找到对所有右端点,满足前缀中 P 减去 U 的个数相同的所有左端点

仔细想想其实也挺显然的,本质是把两种字符的相对数量用前缀和进行维护 。证明也很显然,不妨设 uiu_{i}ui 表示字符串 1∼i1\sim i1∼i 前缀中 uuu 的个数,同理 pip_ipi。那么有:ur−ul−1=pr−pl−1u_r-u_{l-1}=p_r-p_{l-1}ur−ul−1=pr−pl−1ur−pr=ul−1−pl−1u_r-p_r=u_{l-1}-p_{l-1}ur−pr=ul−1−pl−1 这样做的好处是,查区间和会被转化为对一个前缀和,查找另一个前缀和。如果我们边处理前缀和,并以当前位置的前缀和为区间右端点,找前面已经处理出来的左端点(前面的前缀和可以用哈希表或者查找树进行处理),一遍遍历就可以找到所有情况。

所以做了 P-U 的前缀和,同理我们可以维护 Z-2UC-2U 的前缀和,做一遍前缀和这个题就做完了。

所以我们现在只需要再做一个三元组的哈希,然后把哈希扔进哈希表里就行了。

代码:

没有OJ所以不能保证代码正确

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <unordered_map>
using namespace std;
const int maxn=2e5+5;
typedef long long ll;

int n;
string str;
unordered_map<ll,int> mp;

ll s2i(array<int,3> state){
	ll pw=2*maxn;
	return (state[0]+maxn)*pw*pw+
			(state[1]+maxn)*pw+
			(state[2]+maxn);
}

void solve(){
	cin>>n>>str;
	array<int, 3> state{0,0,0};//Z-2U C-2U P-U
	mp.clear();
	mp.insert(make_pair(s2i(state),-1));
	
	int ans=0;
	for(int i=0;i<str.length();i++){
		char c=str[i];
		if(c=='U'){
			state[0]-=2;
			state[1]-=2;
			state[2]-=1;
		}
		else if(c=='Z')state[0]+=1;
		else if(c=='C')state[1]+=1;
		else if(c=='P')state[2]+=1;
		
		ll val=s2i(state);
		if(mp.find(val)!=mp.end())ans=max(i-mp[val],ans);
		else mp.insert(make_pair(val,i));
	}
	
	cout<<ans<<endl;
}


int main(){
	cin.tie(0)->sync_with_stdio(false);
	int T=1;
	cin>>T;
	while(T--)solve();
	return 0;
} 
/*
3
6
ZZUCPC
8
ZZZUUCCP
13
ZZZZZUCPCUCPC

*/
相关推荐
WolfGang007321几秒前
代码随想录算法训练营 Day39 | 动态规划 part12
算法·动态规划
网域小星球12 分钟前
C++ 从 0 入门(五)|C++ 面试必知:静态成员、友元、const 成员(高频考点)
开发语言·c++·面试·静态成员·友元函数
阿Y加油吧13 分钟前
动态规划经典题解:最长递增子序列 & 乘积最大子数组
算法·动态规划·代理模式
|_⊙13 分钟前
C++11 右值引用
开发语言·c++
李昊哲小课18 分钟前
WSL Ubuntu 24.04 GPU 加速环境完整安装指南
c++·pytorch·深度学习·ubuntu·cuda·tensorflow2
Byte不洛20 分钟前
C++继承详解(菱形继承与虚拟继承)
c++·继承·面向对象·菱形继承·虚拟继承
f3iiish20 分钟前
3783. 整数的镜像距离 力扣
算法·leetcode
Not Dr.Wang42223 分钟前
基于matlab的控制系统奈氏图及其稳定性分析
数据结构·算法·matlab
闻缺陷则喜何志丹36 分钟前
【排序 离散化 二维前缀和】 P7149 [USACO20DEC] Rectangular Pasture S|普及+
c++·算法·排序·离散化·二维前缀和
rainbow72424439 分钟前
AI学习路线分享:通用型认证与算法认证学习体验对比
人工智能·学习·算法