CF1605 C. Dominant Character(思维)

题目链接


题意:

给定长度为 n ( 2 ≤ n ≤ 1 0 6 ) (2≤n≤10^6) (2n106) 的仅包含字符'a','b','c'的字符串,找到满足下列条件的最短字串,输出其长度。

  • 长度至少为2;
  • ‘a’出现的次数严格都大于’b’,'c’出现的次数。

思路:

仅包含三种字符,就使得只需要判断少量的情况,其他的情况可以划分为更小规模的问题。这是突破口。

如果一个字符串的长度为2,3,4,7时,需要判断其是否是满足条件的子串(可能满足);但是如果不是,那么其一定可以分解出长度为上述数字的子串是满足的。

比如:
长度为2:aa,本身满足
长度为3:aca,本身满足
长度为4:abca,本身满足
长度为5:abaca,前三个字符满足,长度为3,可以在搜索所有长度为3的子串时找到。
长度为6:abbcaa,最后三个字符满足,长度为3,可以在搜索所有长度为3的子串时找到。
长度为7:abbacca,本身满足
长度为8:abbaacca,中间三个字符满足,长度为3,可以在搜索所有长度为3的子串时找到。
长度为9:abbacacac,第四到六个字符满足,长度为3,可以搜索在所有长度为3的子串时找到。

其他长度的串都可以从中找出长度为2或3或4或7的满足子串。

所以,只需要判断长度为2,3,4,7的所有字串是否满足就可以了。

Code:

const int N = 1000010, mod = 1e9+7;
int T, n, m;
char a[N];
int cnta[N],cntb[N],cntc[N];

bool pd(int len)
{
	for(int i=1;i<=n-len+1;i++)
	{
		int cnt1 = cnta[i+len-1]-cnta[i-1];
		int cnt2 = cntb[i+len-1]-cntb[i-1];
		int cnt3 = cntc[i+len-1]-cntc[i-1];
		if(cnt1>cnt2&&cnt1>cnt3) return 1;
	}
	return 0;
}

int main(){
	Ios;
	
	cin>>T;
	while(T--)
	{
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			cnta[i]=cnta[i-1];
			cntb[i]=cntb[i-1];
			cntc[i]=cntc[i-1];
			if(a[i]=='a') cnta[i]++;
			else if(a[i]=='b') cntb[i]++;
			else cntc[i]++;
		}
		if(pd(2)) cout<<2<<"\n";
		else if(pd(3)) cout<<3<<"\n";
		else if(pd(4)) cout<<4<<"\n";
		else if(pd(5)) cout<<5<<"\n";
		else if(pd(7)) cout<<7<<"\n";
		else cout<<-1<<"\n";
	}
	
	return 0;
}

经验:

看到字符种类较少时,应该想到,较长的长度的串中 可能有 较短长度的子串 所具有的性质。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值