IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> [算法练习]leetcode-6050. 字符串的总引力 -> 正文阅读

[数据结构与算法][算法练习]leetcode-6050. 字符串的总引力

题目链接

力扣

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

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

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

示例 1:

输入:s = "abbca"
输出:28
解释:"abbca" 的子字符串有:
- 长度为 1 的子字符串:"a"、"b"、"b"、"c"、"a" 的引力分别为 1、1、1、1、1,总和为 5 。
- 长度为 2 的子字符串:"ab"、"bb"、"bc"、"ca" 的引力分别为 2、1、2、2 ,总和为 7 。
- 长度为 3 的子字符串:"abb"、"bbc"、"bca" 的引力分别为 2、2、3 ,总和为 7 。
- 长度为 4 的子字符串:"abbc"、"bbca" 的引力分别为 3、3 ,总和为 6 。
- 长度为 5 的子字符串:"abbca" 的引力为 3 ,总和为 3 。
引力总和为 5 + 7 + 7 + 6 + 3 = 28 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/total-appeal-of-a-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

所有的连续子数组是[i, j]? i <= j 的组合,直接枚举所有情况,是O(N^2)的时间复杂度,

可以考虑使用动态规划来分析,假设f(i)是以第i个元素为起始点的所有情况,

f(0) = [0, 0], [0,1], [0,2], [0,3] ……?

f(1) =? [1,1], [1,2], [1,3] ……

可以看到,f(1)的结果可以从f(0)推导出来,分为a[0] == a[1]和a[0] != a[1]的情况,

按照这个思路,可以这样写

class Solution {
public:
    long long appealSum(string s) {
        //init, get sum and each pos
        long long f = 0;
        map<int, vector<int>> pos;
        int len = s.size();
        for (int i = 0; i < len; i++) {
            int k = s[i];
            pos[k].push_back(i);
            f += pos.size();
        }

        long long ans = f;
        vector<int> dt(len);
        vector<long long> fs(len);
        dt[0] = 0;
        fs[0] = f;
        for (int i = 0; i < len-1; i++) {
            //f1 = f0 - dt
            int c = s[i];
            if (s[i] == s[i+1]) {
                fs[i+1] = fs[i] - 1;
                ans += fs[i+1];
                continue;
            }
            //find the pos of i
            vector<int>& arr = pos[c];
            int b = 0;
            int e = arr.size()-1;
            int p = e+1;
            while (b <= e) {
                int m = (b+e)/2;
                if (arr[m] > i) {
                    e = m-1;
                    p = m;
                } else {
                    b = m+1;
                }
            }
            int d = len - i;
            if (p <= arr.size()-1) {
                d = arr[p] - i;
            }
            fs[i+1] = fs[i] - d;
            ans += fs[i+1];
        }     
        return ans;   
    }
};

对于这个题目,也可以假设f(i)是以a[i]为末尾的情况,这样处理,程序写起来更清楚一些,

上面的题目是求>=1的个数,下面的题目比较相似,是求==1的数量,采用f(i)是以a[i]为末尾的情况来处理,

力扣

class Solution {
public:
    int uniqueLetterString(string s) {
        const int n = s.size();
        int tt = 1000000000+7;

        //1.
        // dp[i]: 以s[i]结尾的子字符串的总引力
        // pre_idx[i]: 记录字符 'a'+i 之前出现的位置,如果之前没有出现,就 = -1
        long long dp[n];
        vector<vector<int>> pre_idx(26, vector<int>(2, -1));
    //    int pre_idx[26][2] = {-1};//just the first one is -1

        // 2. initial
        dp[0] = 1;
        int c = s[0] - 'A';
        pre_idx[c][1] = 0;
        
        // 3. 
        long long ans = 1;
        for (int i = 1; i < n; ++i) {
            c = s[i] - 'A'; char of pos i
        //    int len = i - pre_idx[s[i] - 'A'] - 1;
            int dt = 0;
            //not appeared begfore
            if (pre_idx[c][1] == -1) {
                dt = i+1;
            } else {
                dt = (i-pre_idx[c][1])
                 - (pre_idx[c][1]-pre_idx[c][0]); 
                // (pre_idx[c][1]-pre_idx[c][0]) //new
               // - (i-pre_idx[c][0]);//old
            }
            dp[i] = dp[i - 1] + dt;

            pre_idx[c][0] = pre_idx[c][1];
            pre_idx[c][1] = i;

            //
            if (dp[i] > tt) {
                dp[i] = dp[i]%tt;
            }

            ans += dp[i];
            
        }

        // 4. 
        return ans%tt;
    
    }
};

另外子数组的题目,需要考虑使用单调栈找左右区间,

力扣

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-06 11:13:30  更:2022-05-06 11:15:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:35:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码