第十一届蓝桥杯大赛 字串分值 C++

题目:
资源限制
时间限制:1.0s 内存限制:256.0MB

在这里插入图片描述
第十一届蓝桥杯大赛 字串分值 C++_第1张图片
样例输入

ababc

样例输出

21

样例说明

子串  f值
a     1
ab    2
aba   1
abab  0
ababc 1
 b    1
 ba   2
 bab  1
 babc 2
  a   1
  ab  2
  abc 3
   b  1
   bc 2
    c 1

第十一届蓝桥杯大赛 字串分值 C++_第2张图片
思路:
此处思路是从b站中 《2021蓝桥杯直播公开课》中得来的。如果有不懂的同学可以去看一下老师讲的。视频播放地址:https://www.bilibili.com/video/BV1az4y1178E 从48分钟开始看即可。

这里不用暴力法的原因是暴力法的复杂度为n^2.运行超时。这里的思路是从字串的列看,一共有n列,每一列对应一个字符。那么这个字符在一列中的字串中符合条件的总数是:(该字符相同字符的上一个位置 - 该字符的位置)* (该字符相同字符的下一个位置 - 该字符的位置)。例如:下图中的第四个字符B。对应的四个是 AB,ABC,B,BC
第十一届蓝桥杯大赛 字串分值 C++_第3张图片
第十一届蓝桥杯大赛 字串分值 C++_第4张图片
第十一届蓝桥杯大赛 字串分值 C++_第5张图片
所以难点是:怎么求该字符相同字符的上一个位置和下一个位置。具体代码中有解释。

代码:

#include <iostream>

using namespace std;

string str;
int last[26];//用于存放同一个字符的最后一个位置 
int pre[100005];//用于求取每个字符的相同字符的上一个位置 
int next[100005];//用于求取每个字符的相同字符的下一个位置 
//复杂度为 n 
int main()
{
	cin>>str;//输入一个字符串 
	int ans = 0;//存放结果 
	int n = str.size();//计算字符串的长度 
	
	for(int i=0;i<26;i++) last[i] = -1;//全都初始化为-1 
	//这个for循环是从前往后 
	for(int i = 0;i<n;i++)
	{
		int x = str[i] - 'a';//x的值对应某个字符(某个小写字母) 
		pre[i] = last[x];
		last[x] = i;//首先假设 x 所对应的字符是 e ,那么last[x]表示字符e最后出现的位置(位置为i),且一直在更新。
					//所以下次循环中 pre[i]存放的是 本次循环 的e的位置,所以 pre[i]存放的就是最新的e的位置的上一个位置。 
					//所以以此类推,pre[]存放的就是每个字符某个位置的上一个位置 
	}
	
	for(int i=0;i<26;i++) last[i] = n;
	//这个循环是从后向前 
	for(int i=n-1;i>=0;i--)
	{
		int x = str[i] - 'a';
		next[i] = last[x];
		last[x] = i;//此处的解释参考上面pre[] 
	}
	//这个循环就是求结果 
	for(int i =0;i<n;i++)
	{
		// (i - pre[i]) * (next[i] - i)是一个排列组合问题, 
		ans += (long long)(i - pre[i]) * (next[i] - i);
	}
	cout<<ans<<endl;
	return 0;
}

运行结果:
在这里插入图片描述

你可能感兴趣的:(蓝桥杯,c++)