夯实算法-找到最大开销的子字符串

113 阅读2分钟

题目:找到最大开销的子字符串

给你一个字符串 s ,一个字符 互不相同 的字符串 chars 和一个长度与 chars 相同的整数数组 vals 。 子字符串的开销 是一个子字符串中所有字符对应价值之和。空字符串的开销是 0 。 字符的价值 定义如下:

  • 如果字符不在字符串 chars 中,那么它的价值是它在字母表中的位置(下标从 1 开始)。

    • 比方说,'a' 的价值为 1 ,'b' 的价值为 2 ,以此类推,'z' 的价值为 26 。
  • 否则,如果这个字符在 chars 中的位置为 i ,那么它的价值就是 vals[i] 。

请你返回字符串 s 的所有子字符串中的最大开销。

示例 1:

输入: s = "adaa", chars = "d", vals = [-1000]
输出: 2
解释: 字符 "a" 和 "d" 的价值分别为 1 和 -1000 。
最大开销子字符串是 "aa" ,它的开销为 1 + 1 = 2 。
2 是最大开销。

示例 2:

输入: s = "abc", chars = "abc", vals = [-1,-1,-1]
输出: 0
解释: 字符 "a""b""c" 的价值分别为 -1-1-1 。
最大开销子字符串是 "" ,它的开销为 00 是最大开销。

提示:

  • 1<=s.length<=1051 <= s.length <= 10^5
  • s 只包含小写英文字母。
  • 1<=chars.length<=261 <= chars.length <= 26
  • chars 只包含小写英文字母,且 互不相同 。
  • vals.length==chars.lengthvals.length == chars.length
  • 1000<=vals[i]<=1000-1000 <= vals[i] <= 1000

解题思路

由题意分析可用动态规划思路:dp[i]表示以 chars[i] 结尾的子字符串的最大开销,则动态规划转移方程为:dp[i] = Math.max(只取当前字符的最大开销, dp[i-1])

因为 dp[i] 取值仅与 dp[i-1] 有关,所以可用 原地dp,只需定义一个 pmax,表示以前一个字符结尾的字符串所能得到的最大开销。

代码实现

public int maximumCostSubstring(String s, String chars, int[] vals) {
    int n = s.length();
    int[] m = new int[26];

    Arrays.fill(m, 1001);
    for (int i = vals.length - 1; i >= 0; --i) {
        m[chars.charAt(i) - 'a'] = vals[i];
    }

    int ret = 0;
    int pmax = 0;
    for (int i = 0; i < n; ++i) {
        int idx = s.charAt(i) - 'a';
        int cur = m[idx] == 1001 ? idx + 1 : m[idx];
        pmax = Math.max(cur, pmax + cur);
        ret = Math.max(pmax, ret);
    }

    return ret;
}

运行结果

zby1.png

复杂度分析

  • 空间复杂度:O(1)
  • 时间复杂度:O(n)

掘金(JUEJIN) 一起分享知识, Keep Learning!