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

该博客主要介绍了一种算法,用于计算给定字符串中所有非空子串的不同字符个数(分值)之和。解题思路是通过记录每个字符上一次出现的位置,计算当前字符可以被多少子串包含,从而得出总和。提供的C++代码实现了这一算法,输出了样例输入"ababc"的正确结果28。
摘要由CSDN通过智能技术生成

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

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

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

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

样例输入
ababc

样例输出
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[s[i]] 记录字母 s[i] 上一次出现的位置;
那么往左最多能延伸到 a[s[i]] + 1,其到第 i 个字母一共有 i - a[s[i]] 个字母;
同理往右最多能延伸到 n,其到第 i 个字母一共有 n - i + 1 个字母;

以样例 ababc 为例,求第 2 个 'a' 的贡献度

第一个 'a' 的下标为 1,第二个 'a' 的下标为 3;

所以向左最多延伸到 'b',即下标 2;向右最多能延伸到 'c',即下标 5;

因此 (3 - 1) * (5 - 3 + 1) = 6

第 2 个 'a' 能被以下 6 个子串所包含:

1、a        2、ab        3、abc        4、ba        5、bab        6、babc
二者相乘,就是该字母被不同子串所包含的总次数;

5 + 8 + 6 + 4 + 5 = 28

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int a[200];
int main()
{
    string s;
    cin >> s;
    int n = s.size();
    s = ' ' + s;//让字符串的下标从 1 开始,否则在算第一个字母时,就会出现 (0 - 0) * (n - 0 + 1) = 0 这种情况,但第一个字母是有 1 个贡献度的
    LL ans = 0;
    for (int i = 1; i <= n; i ++)
    {
        ans += (LL)(i - a[s[i]]) * (n - i + 1);
        a[s[i]] = i;
    }
    cout << ans << "\n";
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值