原题
题目描述
对于一个字符串S,我们定义S的分值fs为s中恰好出现一次的字符个数,例如f(aba)=1,f(abc)=3,f(aaa)=0。现在给定一个字符串S0-n-1,请你计算对于所有S的非空子串的和是多少。
输入描述
输入一行包含一个由小写字母组成的字符串 S
输出描述
输出一个整数表示答案
输入输出样例
输入
ababc
输出
21
分析
-
举个栗子:
-
暴力遍历,会超时
-
不会超时的方法:
考虑每个字符串最多能贡献几分
思路代码都特别简单让我们来看看哈
要点:
对输入的字符串的头尾进行补充
,为了统一处理,同时也是判断终止的字符。- 考虑每一个字符的贡献分数,以第一个字符为例,左右移动,每移动一格加一分,截止条件为:
遇到下一个a,或者遇到终止字符。
- 字符左边得分为左移动次数,字符右边得分为右移动次数,
本字符贡献得分为左右相乘
。
代码+注释
s = input()
# 对输入的字符串的头尾进行补充,为了统一处理。
# 0是判断终止的字符,同时保证了序号和索引的统一,第一个字符对应的索引就是1
s = "0" + s + "0"
length = len(s)
def find(i):
# 左下标为当前位置左移一个
left = i - 1
# 右下标为当前位置右移一个
right = i + 1
# 遇到下一个相同字符,或者遇到终止字符就停止,没遇到就继续移动
while left != 0 and s[left] != s[i]:
left -= 1
# 计算左得分公式为当前遍历对象下标-左下标
left_score = i - left
while right != length - 1 and s[right] != s[i]:
right += 1
# 计算右得分公式为右下标-当前遍历对象下标
right_score = right - i
# 当前遍历对象得分为左得分乘以右得分
score = left_score * right_score
return score
# 从第一个字符开始遍历到倒数第二个,倒数第一是补充的0
# 对每一个被遍历对象执行查找分数操作
# 对所有对象的分数转为列表并求和
print(sum([find(i) for i in range(1, length - 1)]))
付费咨询
微信:x15511371025
QQ:1142926171