P8715 [蓝桥杯 2020 省 AB2] 子串分值

本文介绍了如何解决蓝桥杯2020竞赛中的一个问题,通过记录字符串中每个字符及其出现位置,计算满足条件的子串个数。使用两个临时数组分别存储字符的上一次和下一次出现位置,然后遍历字符串计算总分值。
摘要由CSDN通过智能技术生成

一、题目描述

P8715 [蓝桥杯 2020 省 AB2] 子串分值

二、问题简析

记录字符串 s s s 的 第 i i i 个字符 s i s_i si 0 ≤ i < s . s i z e 0\leq i<s.size 0i<s.size)上一次出现的位置 p r e i pre_i prei、下一次出现的位置 n e x i nex_i nexi,仅包含 s i s_i si 的字串个数为 ( i − ( p r e i + 1 ) + 1 ) ∗ ( n e x i − 1 − i + 1 ) (i - (pre_i + 1) + 1) * (nex_i - 1 - i + 1) (i(prei+1)+1)(nexi1i+1),即 ( i − p r e i ) ∗ ( n e x i − i ) (i-pre_i)*(nex_i-i) (iprei)(nexii)。只需要遍历所有的 s i s_i si,将所有字串个数相加就是所求。

p r e i pre_i prei:因为字符串里只有 26 26 26 个小写字母,所以创建一个容量为 26 26 26 的临时数组 rec[26],记录对应字母上次出现的下标rec[0] 对应 arec[1] 对应 b,以此类推)。

  • 1、因为要记录上一次出现的位置,所以要从左往右遍历,并更新相应的 rec[i]
  • 2、需要注意每个字母首次出现的 p r e i pre_i prei,因为是首次出现,所以下标从 0 0 0 i i i 的字母都可以是字串的开头,即 p r e i + 1 = = 0 pre_i+1==0 prei+1==0。因此,rec[26] 要初始化为 -1

n e x i nex_i nexi:与 p r e i pre_i prei 类似,也需要一个临时数组 rec[26]。不同点:

  • 1、从右往左遍历,并更新相应字母的下标
  • 2、rec[26] 初始化为 s.size,因为每个字母最后一次出现时,下标从 i i i s . s i z e − 1 s.size-1 s.size1 都可以作为字串的结尾,即 n e x i − 1 = = s . s i z e − 1 nex_i-1==s.size-1 nexi1==s.size1

三、AC代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int MAX = 1e5 + 3;
int pre[MAX], nex[MAX], rec[30];
string s;

int main()
{
	#ifdef LOCAL
	freopen("test.in", "r", stdin);
	#endif
	
	cin >> s;
	int sSize = s.size();
	fill(rec, rec + 26, -1);
	for (int i = 0; i < sSize; i++)
	{
		pre[i] = rec[s[i] - 'a'];
		rec[s[i] - 'a'] = i;
	}
	fill(rec, rec + 26, sSize);
	for (int i = sSize - 1; i >= 0; i--)
	{
		nex[i] = rec[s[i] - 'a'];
		rec[s[i] - 'a'] = i;
	}
	
	ll ans = 0;
	for (int i = 0; i < sSize; i++)
	{
		ans += (i - pre[i]) * (nex[i] - i);
	}
	cout << ans << endl;
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值