历届试题-子串分值和(蓝桥十一届)

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


问题描述
对于一个字符串 ,我们定义  的分值  为  中出现的不同的字符个数。例如 "aba""abc", "aaa"。

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

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

输出格式
输出一个整数表示答案。

样例输入
ababc
Data
样例输出
28

样例说明
子串  f值
a     1
ab    2
aba   2
abab  2
ababc 3
 b    1
 ba   2
 bab  2
 babc 3
  a   1
  ab  2
  abc 3
   b  1
   bc 2
    c 1

思路:根据样式输出看出规律

在这里插入图片描述

  • 第一个字符a他只出现了五次,我们就可以相当于用它的下标(假设下标从0开始),就可以得到(下标 + 1)x(s长度 - 下标) = 1x5 = 5,并且把a出现的位置记录下来,a的位置为1。
  • 第二个字符b同理出现的次数为(下标 + 1)x(s长度 - 下标)= 2x4 = 8,并且把b的位置记录下来,b位置为2。
  • 第三个字符是a,此前a的位置已经出现过了,实质第三个a出现过9次,但根据题目有用的只有6次,这里就可以用到((s长度 - 下标))x((当前位置 - 前一个位置)) = 3x2 = 6。
  • 第四个同理第三个a,((s长度 - 下标))x((当前位置 - 前一个位置)) = 2x2 = 4。
  • 第五个字符c还没有出现过所以直接(下标 + 1)x(s长度 - 下标) = 5x1 = 5。
    从而得到ababc对应得是5,8,6,4,5加起来28。
#include<stdio.h>
#include<string.h>

int main()
{
    long long i,n,sum = 0;
    int a[26] = {0}; //代表每个字符的出现位置当为0的时候表示之前没有出现过
    char s[100000];
    scanf("%s",s);
    n = strlen(s);
    for(i = 0; i < n; i++)
    {
        if(a[s[i] - 'a'] == 0)  //判断该字符是否出现过
        {
            sum = sum + (i + 1)*(n - i); //把单个字符的值加起来((下标 + 1)x(s长度 - 下标) )
            a[s[i] - 'a'] = i + 1;       //保存字符的位置
        }
        else
        {
            sum = sum + (i + 1 - a[s[i] - 'a']) * (n - i); //之前出现过的字符,现在再次出现的值((s长度 - 下标))x((当前位置 - 前一个位置))
            a[s[i] - 'a'] = i + 1;   //更新位置
        }
    }
    printf("%lld",sum);
    return 0;
}


在这里插入图片描述

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小满@

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

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

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

打赏作者

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

抵扣说明:

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

余额充值