CF日常刷题篇:1535C Unstable String

在这里插入图片描述Unstable String

大致题意

如果一个字符串形如 010101010... 010101010... 010101010... 10101010... 10101010... 10101010...,则该字符串为不稳定字符串。字符串中只含有 1 , 0 , ? 1, 0, ? 1,0,?,其中 ? ? ?可以看作 1 1 1 0 0 0。求字符串的子串(连续)中有多少不稳定字符串。

Input

3
0?10
???
?10??1100

Output

8
6
25

一道经典的算法题,考虑如何去减少复杂度,一步步让算法变得更加高效。

以此题为例,讲一下作为一个OIer应该如何去思考问题。

首先注意到,字符串只有 1 , 0 , ? 1,0,? 1,0,?三种类型,而 ? ? 可作为特殊的两用存在,故在不考虑问号存在的情况下考虑如何计数。

无问号

选择最为朴素的做法,三个循环,前两个为两下标i和j,第三个循环计算以 i i i开头以 j j j收尾的子字符串是否稳定。很明显时间复杂度为 O ( n 3 ) O(n^3) O(n3),简单但时间无法承受。

考虑优化,因为是连续字串,且发现一个不稳定字符串的连续子串一定不稳定(传递性),因此无需重复计算,稍微思考则可认定使用扫描法计算数目。

运用扫描法我们便可得到一个子串集:他们互不相连,并且无法找到长度总和比他们更长的字符串。且时间复杂度为 O ( n ) O(n) O(n),可以通过。

每一次扫描到一个位置时,可以判断其是否与上一个位置不同,若是则 v a l u e + 1 value+1 value+1,否则 v a l u e value value清除为 1 1 1.每一次扫描都需要加上这一次的 v a l u e value value值,得到结果。

有问号

考虑问号对字符串的影响,可以发现,

如果问号是连续的,则无需考虑其影响,这一个子字符串一定不稳定。且可以发现,如果该子串与另一个不稳定子串相邻,那么它们组合便可以得到一个更加长的不稳定子串。现在我们得到了以下的结论:

  1. A substring of the unstable string is an unstable string.
  2. If a string is all ‘?’, then another unstable string combined with it is unstable.

现在我们就能够思考这一种情形了:

如: “010101?????0101”

在这里插入图片描述
1和2可以组成不稳定子串,2和3可以组成不稳定子串,但1,2和3不能组成,原因是不论?替换成1或0,都不能使其排成0101的形式。

当扫描到3时,我们需要放弃1结束时的 v a l u e value value值,考虑如此,我们需要独特的计数方法,这里我们应用一个 m a r k mark mark值,记录出现连续的 ? ? 的个数,当连续的 ? ? 结束后,我们需要判断这一个子串3是否与前前一个子串1连接。

这里选择将?进行替换,替换的内容依据前一子串1而定。让1和2能够成为一个不稳定子串。此时3能否与1和2联系便可直接从被替换的2出发。
在这里插入图片描述

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;

int main() {
	int T;
	scanf("%d", &T);
	
	while(T-- > 0) {
		string s;
		cin>>s;
		
		long long mark = 0, v = 0, ans = 0;
		for(int i = 0; i < s.size(); i++) {
			if(s[i] != '?') {
				if(s[i] == s[i-1]) v = mark;
				mark = 0;
			}else {
				s[i] = s[i-1] == '1' ? '0' : '1';
				mark++;
			}
			v++;
			ans += v;
		}
		
		printf("%lld\n", ans);
	}
}

对了,数据范围大,记得写LL。

其他练习题:

1535D Playoff Tournament

同样是一道只含“0,1,?”的字符串,但涉及了一些修改,查询的操作。思路和树有关

1536B Prinzessin der Verurteilung

一道有关字典序的暴力题。思路很有趣,博主暂时只想到了进制转换和BFS的思路,欢迎私信讨论。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值