字符串的总引力

字符串的 引力 定义为:字符串中 不同 字符的数量。

例如,"abbca" 的引力为 3 ,因为其中有 3 个不同字符 'a'、'b' 和 'c' 。
给你一个字符串 s ,返回 其所有子字符串的总引力 。

子字符串 定义为:字符串中的一个连续字符序列。

1. 区间贡献法

从左往右遍历,优先计算左边同一字符做出的贡献,后面出现的相同字符不再计入贡献,被前面覆盖,只计算不受前面相同字符影响的区间
相比其他贡献法的题目更好计算,只需考虑左侧的辖域范围,右侧默认完全统辖
故需要记录每一类字符上一次出现的位置

class Solution {
public:
    long long appealSum(string s) {
        vector<int> lasts(26, -1);
        long long res = 0;
        for(int i = 0; i < s.size(); ++i) {
            res += 1ll * (i - lasts[s[i] - 'a']) * ((int)s.size() - i);
            lasts[s[i] - 'a'] = i;
        }
        return res;
    }
};

2. 转移法

考虑两组相邻的子串:以 s[i−1] 结尾的子串、以 s[i]结尾的子串。
以 s[i] 结尾的子串,可以看成是以 s[i−1] 结尾的子串,在末尾添加上 s[i] 组成。
从左往右遍历 s,考虑将 s[i] 添加到以 s[i−1] 结尾的子串的末尾。
添加后,这些以 s[i−1] 结尾的子串的引力值会增加的值,等价于方法一种s[i]统辖的左侧范围

class Solution {
public:
    long long appealSum(string &s) {
        long long ans = 0;
        vector<int> last(26, -1); // 初始化成 -1 
        for (int i = 0, sum = 0; i < s.size(); ++i) {
            sum += i - last[s[i] - 'a']; //以当前遍历位置为结尾的子字符串总吸引力
            ans += sum; //统计所有位置子字符串
            last[s[i] - 'a'] = i;//更新辖域
        }
        return ans;
    }
};
posted @ 2023-10-29 13:28  失控D大白兔  阅读(14)  评论(0编辑  收藏  举报