• 2370. 最长理想子序列(每日一难phase2--day6)


    2370. 最长理想子序列

    给你一个由小写字母组成的字符串 s ,和一个整数 k 。如果满足下述条件,则可以将字符串 t 视作是 理想字符串 :

    • t 是字符串 s 的一个子序列。
    • t 中每两个 相邻 字母在字母表中位次的绝对差值小于或等于 k 。

    返回 最长 理想字符串的长度。

    字符串的子序列同样是一个字符串,并且子序列还满足:可以经由其他字符串删除某些字符(也可以不删除)但不改变剩余字符的顺序得到。

    注意:字母表顺序不会循环。例如,‘a’ 和 ‘z’ 在字母表中位次的绝对差值是 25 ,而不是 1 。

    示例 1:

    输入:s = “acfgbd”, k = 2
    输出:4
    解释:最长理想字符串是 “acbd” 。该字符串长度为 4 ,所以返回 4 。
    注意: “acfgbd” 不是理想字符串,因为 ‘c’ 和 ‘f’ 的字母表位次差值为 3 。

    示例 2:

    输入:s = “abcd”, k = 3
    输出:4
    解释:最长理想字符串是 “abcd” ,该字符串长度为 4 ,所以返回 4 。

    提示:

    1 <= s.length <= 1e5
    0 <= k <= 25
    s 由小写英文字母组成

    解析:

    • 想到字符串的子序列,以及顺序就应该联想到dp,枚举每个元素作为最后一个字符,寻找与前边字符的关系。
    • 例如:s = “acfgbd”, k = 2,假设子序列以g结尾,k=2,那么前边一个字符的范围就是
      [ down = max(0,int(s[i]-‘a’)-k) , up = min(25,int(s[i]-‘a’)+k) ],因此可以寻找之前以这些字符为结尾的最大值+1(当前字符),就是以g结尾的最大值
    • 假如当前字符为 ‘g’ ,k=2,可能出现多次e,可以断定一定是最后一个e组成的子序列最长’‘aeedddeef’',因为后边串包含前边串,这样只需要记录最后一次出现时对应的子序列长度,因此就可以优化空间了。

    代码:

    class Solution {
    public:
    ///  记录每个字母出现的最后一个位置,dp
        int longestIdealString(string s, int k) {
            int n=s.size();
            // 每个位置最长子序列
            int dp[n];
            // 每个字符最后出现的位置
            int c[26];
            memset(c,-1,sizeof(c));
            for(int i=0;i<n;i++){
                // 符合第一种情况
                int down = max(0,int(s[i]-'a')-k);
                int up = min(25,int(s[i]-'a')+k);
                int res=1;
                // 枚举所有符合的字符
                for(int i=down;i<=up;i++){
                	// 如果这个字符没出现过,长度为res=max(1,res)
                    if(c[i]==-1)
                        continue;
                    else
                        res = max(res,dp[c[i]]+1);
                }
                dp[i]=res;
                // 更新最后出现的位置
                c[s[i]-'a']=i;
            }
            return *max_element(dp,dp+n);
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    // 压缩dp:

    class Solution {
    public:
        int longestIdealString(string s, int k) {
            int n=s.size();
            ///  直接记录每个字符最后一次的最大子序列长度
            int c[26];
            memset(c,-1,sizeof(c));
            for(int i=0;i<n;i++){
                // 符合第一种情况
                int down = max(0,int(s[i]-'a')-k);
                int up = min(25,int(s[i]-'a')+k);
                //printf("%d,%d\n",down,up);
                int res=1;
                for(int j=down;j<=up;j++){
                    res = max(res,c[j]+1);
                }
                c[s[i]-'a']=res;
            }
            return *max_element(c,c+26);
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    使用Docker安装和部署kkFileView
    Hbuilder打包成APP流程,以及遇到的坑
    ROS源代码阅读(1)
    网站搜索引擎优化SEO面试题库和答案(SEO 主管、网站管理员、网站优化师、数字营销专家等)
    Redis集群
    如何绘制Top级美图?20+案例分享
    wangEditor 富文本编辑
    虚拟 DOM 和 diff 算法
    《解密并行和分布式深度学习:深度并发分析》摘要记录
    【Vue组件之间的三种通信】
  • 原文地址:https://blog.csdn.net/weixin_42051691/article/details/126660385