试题 历届试题 子串分值和【第十一届】【省赛】【B组】

子串分值和满分解法


一、完整题目

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二、具体思路

1.暴力递归

利用递归的思想,求出每一个字串,并统计每一个字串的分值,最后进行统计累加,求得结果,求字串的顺序为:

  1. 首先,一个完整的串,将一个完整的串每次去点最后一个字符
  2. 再次,去掉串的首个字符,重复1的操作
  3. 重复2的操作直至串为空

在求出每个子串,统计字符数量即可

2.统计贡献值

正常求字串要横向一行一行看,我们把思路打开,竖着看,看每一列的字符出现了几次,将次数统计起来即可,在网上找到了一个示意图:
在这里插入图片描述
来源:https://img-blog.csdnimg.cn/20210413181240678.png

可以总结出公式:

  • 该字符第一次出现时:出现次数=(下标+1)x(字符串长度-下标)
  • 该字符之前出现过时:出现次数=(字符串长度-下标)x(当前位置-之前出现的位置)

三、编写代码

1.暴力递归

#include <stdio.h>
#include <string.h>

#define MAX 100000//最大长度

int difStr(char s[],int len)//求字串的分值
{
    if(len==0) return 0;//结束条件

    int i,cnt=0;
    int a[26]={0};//统计是否存在

    for(i=0;i<len;i++) a[s[i]-'a']++;//计数
    for(i=0;i<25;i++) if(a[i]!=0) cnt++;//统计出现不同字母的个数

    cnt+=difStr(s,len-1);//递归实现
    return cnt;//返回此字串的分值
}

int f(char s[],int len)//统计所有字串的分值和
{
    if(len==0) return 0;//结束条件

    int sum=0;//分值和

    sum+=difStr(s,len);//求出此轮递归的字串分值和

    sum+=f(s+1,len-1);//递归求出其他字串的和
    return sum;//返回所有字串的分值和
}

int main()
{
    char s[MAX];//开数组
    int sum,len;

    scanf("%s",&s);//输入字符串

    len=strlen(s);//求输入的字符串长度
    
    printf("%d",f(s,len));//打印结果

    return 0;
}

2.统计贡献值

#include<stdio.h>
#include<string.h>

#define MAX 100000//最大长度

typedef long long int LLint;

int main()
{
    LLint i,len,sum=0;
    int a[26]={0}; //用于统计出现的字符数
    char s[MAX];

    scanf("%s",s);//输入字符串

    len=strlen(s);//求输入字符串长度

    //求字串分值和
    for(i=0;i<len;i++)
    {
        if(a[s[i]-'a']==0)//判断该字符是否出现过
        {
            sum=sum+(i+1)*(len-i);//把单个字符的值加起来
            a[s[i]-'a']=i+1;//保存字符的位置
        }
        else
        {
            sum=sum+(i+1-a[s[i]-'a'])*(len-i);//之前出现过的字符,现在再次出现的值
            a[s[i]-'a']=i+1;//更新位置
        }
    }

    printf("%lld",sum);//打印输出
    return 0;
}

四、测评结果

1.暴力递归

只过了50%的测试点,之后的测试点会超时

2.统计贡献值

在这里插入图片描述

在这里插入图片描述


五、总结评价

综上可以看出,递归的方法虽然思路清晰,编写简单,但是比较暴力时间复杂度较高;而统计贡献值的方法,不容易想到,但是十分简单。
所以,假如我们是生活在一幅画中,要时常跳出来,看一看画的全貌,在跳回去,而不是埋头苦干,有时候选择比努力更重要。

有问题欢迎各位大佬指出
蓝桥杯系列将持续更新,欢迎关注,一起学习

  • 27
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

S1XmKl

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

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

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

打赏作者

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

抵扣说明:

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

余额充值