子串分值——第十一届蓝桥杯AC

子串分值——第十一届蓝桥杯AC

题目描述

原题地址
在这里插入图片描述

对于一个字符串 S,我们定义 S 的分值 f ( S ) 为 S 中恰好出现一次的字符个数。


例如 f ( “ a b a ” ) = 1 ,f ( “ a b c ” ) = 3
f(“aaa”)=0。


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




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


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


输入样例
ababc


输出样例
21

思路

  • 我们要求所有非空子串中出现次数为一的元素的和,也就是求基于字符串每一个元素达到出现一次的所有字符串之和;
  • 用 pre[i] 记录第 i 个字母上一次出现的位置,那么往左最多能延伸到 pre[i] + 1,其到第 i 个字母一共有 i - pre[i] 个字母;
  • 用 next[i] 记录第 i 个字母下一次出现的位置,同理往右最多能延伸到 next[i] - 1,其到第 i 个字母一共有 next[i] - i 个字母;
  • 二者相乘,就是该字母出现一次的所有子串的数目;

代码

#include <iostream>
// memset 需要 cstring 头文件
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int pre[N], nex[N];
int idx[26];
int main() {
    
    
    string s;
    cin >> s;
    s = " " + s;
    ll res = 0;
    int n = s.size();
    for (int i = 1; i < n; ++i) {
    
    
        pre[i] = idx[s[i] - 'a'];
        idx[s[i] - 'a'] = i;
    }
    for (int i = 0; i < 26; ++i)
        idx[i] = n;
    for (int i = n - 1; i; --i) {
    
    
        nex[i] = idx[s[i] - 'a'];
        idx[s[i] - 'a'] = i;
    }
    for (int i = 1; i < n; ++i) {
    
    
        res += (ll) (i - pre[i]) * (nex[i] - i);
    }
    cout << res;
    return 0;
}


以下题目和该题相似,可以参考。欢迎大家批评指正
[蓝桥杯2020初赛] 子串分值和 题解 C++

猜你喜欢

转载自blog.csdn.net/weixin_64632836/article/details/128947078