蓝桥杯刷题011——子串分值和

子串分值和

【题目描述】

        对于一个字符串S,我们定义S的分值f(S)为S中出现的不同的字符个数。例如f("aba ')=2,f("abc")= 3,f(“aaa”)=1。现在给定一个字符串 S[0...n-1](长度为n),请你计算对于所有S的非空子串S [i...j](0≤i≤j<n) ,f(S[i.….j])的和是多少。

输入描述

输入一行包含一个由小写字母组成的字符串 S。

其中,1≤n≤10^5。

输出描述

输出一个整数表示答案。

输入输出样例

输入

ababc

输出

28

【问题解析】 

一、暴力破解

  1. 找出所有可能的子串;
  2. 统计每个子串的分值;
str1 = input()
ans = 0

# 两个for循环找出所有可能的子串
for i in range(len(str1)):
    for j in range(i+1,len(str1)+1):
        s = str1[i:j]
        set1 = set(s)    # 用集合去重
        ans += len(set1)
print(ans)

 超时了,只能通过40%的测试。 

 二、统计个体贡献

        由于f(S)表示S中出现的不同的字符个数,也就是说对于字符串aaa而言,3个a中只有一个a可以对其产生贡献。那么我们不妨将第1个、第2个a的贡献抹去,只计算第3个a的贡献。即当一个字符ch在字符串中出现了多次,我们只计算最靠右的ch对答案的贡献(其它ch在该字符串的贡献都被抹去了)。
        【做法】定义right_index表示第i个字符下一次出现的位置。那么要让第i个字符能对答案产生贡献,则包含它的子串的左端点的取值范围必须在[1 , i]之间(即左端点没有限制),右端点的取值范围必须在[i+ 1, right_index - 1]之间(若右端点的取值大于等于right_index,则该字符对该子串贡献将被抹除)。其对答案的贡献为限制左右端点取值范围后所能构造出的子串的个数,即i*(right_index - i)。

        如上图,左端点:[0]右端点:[1,4]记在第一个a的贡献;左端点:[0,5]右端点:[6,8]记在第二个a的贡献;左端点:[0,9]右端点:[10]记在第三个a的贡献。

s=input()
ans=0
for i,c in enumerate(s):    # 取出索引i和元素C
  r=i+1                     # 右端点:当前索引的下一个
  while r<len(s):           # 右端点从当前索引的下一个到末尾进行遍历
    if s[r]!=c:r+=1         # 不是相同的字符,右端点向右移一位
    else:break              # 是相同的字符,结束
  ans+=(i+1)*(r-i)          # 贡献:左边(所有)*右边(没有相同)。i+1是因为i从0开始
print(ans)

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小叶pyか

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值