【python】打卡第三天——子串分值 

让机器理解语言 2023-02-01 18:22:53

题目描述
对于一个字符串 S,我们定义 S 的分值 f(S) 为 S 中恰好出现一次的字符个数。例如 f(aba) = 1,f(abc) = 3, f(aaa) = 0。

现在给定一个字符串 (长度为 n,),请你计算对于所有 S 的非空子串 (0≤i≤j<n),的和是多少。

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

输出描述
输出一个整数表示答案。

输入输出样例
输入

ababc
输出

21


【例题分析】

法一:暴力破解(可得部分分数)

找出所有可能的子串;
统计每个子串的分值

法二:统计每个字符的贡献

        考虑枚举字符串的每个字符对答案的贡献。让第i个字符能对答案产生贡献,必须子串中该字符只出现一次。对哪些子串第i个字符只出现一次?看看下图分析。

【做法】定义left_index表示第i个字符上一次出现的位置,right_index表示第i个字符下一次出现的位置。那么要让第i个字符能对答案产生贡献(即该子串内第i个字符只恰好出现一次的),则包含它的子串的左端点的取值范围必须在[left_index + 1 , i]之间,右端点的取值范围必须在[i+1, right_index - 1]之间。

【代码演示】

chars = input()
len_str = len(chars)
left = [None for _ in range(len_str)]   # 左边第一次出现的相同字符
right = [None for _ in range(len_str)]  # 右边第一次出现的相同字符
for i in range(len_str):    # 遍历所有字符,统计每个字符的贡献
    char = chars[i]
    for j in range(i - 1, -1, -1):  # 向左边找左端点
        left_char = chars[j]
        if left_char == char:           # 出现相同的字符
            left[i] = j                 # 保存到left
            break
    for j in range(i + 1, len_str): # 向右边找右端点
        right_char = chars[j]
        if right_char == char:          # 出现相同的字符
            right[i] = j                # 保存到right
            break
result = 0
for i in range(len_str):
    if left[i] == None and right[i] == None:    # 左右端点没有相同字符(从头到尾只有一个字符)
        result += (i + 1) * (len_str - i)       # 组合:左边*右边
    elif left[i] == None:                       # 只有左边全没相同
        result += (i + 1) * (right[i] - i)      # 组合:左边*右边(没有)
    elif right[i] == None:                      # 只有右边全没相同
        result += (i - left[i]) * (len_str - i) # 组合:左边(没有)*右边
    else:                                       # 只有都有相同的
        result += (right[i] - i) * (i - left[i])# 把左右没有相同的部分组合:左边(没有)*右边(没有)
print(result)

 

...全文
15 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

30,360

社区成员

发帖
与我相关
我的任务
社区描述
打造最热爱学习的高校社区,帮助大家提升计算机领域知识,带大家打比赛拿奖,提高自我,希望大家共同创造良好的社区氛围。
社区管理员
  • 川川菜鸟
  • 亡心灵
  • 星辰菜鸟
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

监督大家学习,每日学习打卡,以投稿形式打卡。扫码关注公众号,可加入粉丝群和领取大量资源。

试试用AI创作助手写篇文章吧