《关于蓝桥杯--字符串简写》

首先题目大致意思很简单,

就是两个要求:一、首尾字母符合要求,二、长度符合要求

那我们就有一个很朴素的想法就是暴力遍历。。但是看数据范围,

这种暴力解法是一定会tle的。那我们不妨换一种思想;

我们要统计有多少个子串符合要求,那也就是当我们遍历到c2的时候,看看前面有多少个符合要求的c1(长度要求),这如果再简化一下,就变成了统计c2之前有多少个c1,只不过需要判断一下长度;

这一下就有了解决问题的思路,用前缀和算法

前缀和算法,故名思意就是一个统计前面所有的和的算法,它可以实现O(1)查找数组中某一位之前的和;

而我们这里不妨可以将问题简化为,遍历一遍s字符串,并且遇到一次c2,判断一下有多少个c1符合要求,并且加到结果中去;

#define  _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using i64 = long long;
using namespace std;
int main()
{
	int k;
	cin >> k;

	string s;
	cin >> s;

	char c1, c2;
	cin >> c1 >> c2;

	vector<int> prefix(s.size());//prefix是用来统计当前位置之前出现了多少个c1
	long long sum = 0;
	for (int i = 0, size = s.size(); i < size; ++i)
	{
		if (i)
		{
			//前缀和
			prefix[i] += prefix[i - 1];
		}

		if (s[i] == c1)
		{
			++prefix[i];
		}
		if (s[i] == c2 && i - k + 1 >= 0)
		{
			//i - k + 1 是c1坐标 ,必须>=0
			sum += prefix[i - k + 1];
		}

		cout << sum;
	}
	return 0;
}

这里s代表要进行操作的字符串,prefix数组用于表示前缀和数组

我们首先设一个for循环对字符串s进行遍历,然后在内部进行前缀和操作(如果下标大于0,就让后一位 += 前一位,这样就可以实现O(1)查找某一位之前的和),并且在遇到c1的时候就prefix[i] ++,如果遇到c2,我们需要进行判断

判断的条件是啥?

题目中很明确的说了长度要求为k,那如果c2的下标为i,那么c1的下标经过计算应该为 i - k + 1

c1既然是在这个合法字符串中,那下标一定得 >=0

所以判断条件为 遍历到c2 且 c1下标>= 0

同时,如何计算出c2之前有多少个c1符合要求?

i - k + 1其实应该是擦着边过的要求,如图

对于这样一个黑长条当作 字符串s,那我里面随机出现的c1,c2可以是这样

如果对于中间某段,有这样的情况:

如果c2的下标为k,那么在c2左边,最靠近c2的一个c1坐标应该是 i - k + 1,这是最差情况,长度刚好为k,那之前还有若干个c1,所以我们可以在答案中加上prefix[i- k + 1] ;

其实也就是标标准准的前缀和了,统计该c1之前出现的c1个数。

希望我写的内容对大家有所帮助。谢谢大家! 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值