(蓝桥杯)历届试题 (c语言) 子串分值和

问题如下
在这里插入图片描述在这里插入图片描述看到题目第一想法是进行暴力解决(通过遍历所有的子串然后进行累加把结果得出来),结果果然是超过时间限制。
在这里插入图片描述之后通过寻找字符间的规律可以得到一个式子,通过这个式子可以得到遍历一次就可以把子串分值都加起来,这样就不会超过时间限制了。
例如:s = "ababc"的这个字符串
在这里插入图片描述

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

  • 25
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值