返回介绍

solution / 2700-2799 / 2746.Decremental String Concatenation / README_EN

发布于 2024-06-17 01:03:00 字数 8739 浏览 0 评论 0 收藏 0

2746. Decremental String Concatenation

中文文档

Description

You are given a 0-indexed array words containing n strings.

Let's define a join operation join(x, y) between two strings x and y as concatenating them into xy. However, if the last character of x is equal to the first character of y, one of them is deleted.

For example join("ab", "ba") = "aba" and join("ab", "cde") = "abcde".

You are to perform n - 1 join operations. Let str0 = words[0]. Starting from i = 1 up to i = n - 1, for the ith operation, you can do one of the following:

  • Make stri = join(stri - 1, words[i])
  • Make stri = join(words[i], stri - 1)

Your task is to minimize the length of strn - 1.

Return _an integer denoting the minimum possible length of_ strn - 1.

 

Example 1:

Input: words = ["aa","ab","bc"]
Output: 4
Explanation: In this example, we can perform join operations in the following order to minimize the length of str2: 
str0 = "aa"
str1 = join(str0, "ab") = "aab"
str2 = join(str1, "bc") = "aabc" 
It can be shown that the minimum possible length of str2 is 4.

Example 2:

Input: words = ["ab","b"]
Output: 2
Explanation: In this example, str0 = "ab", there are two ways to get str1: 
join(str0, "b") = "ab" or join("b", str0) = "bab". 
The first string, "ab", has the minimum length. Hence, the answer is 2.

Example 3:

Input: words = ["aaa","c","aba"]
Output: 6
Explanation: In this example, we can perform join operations in the following order to minimize the length of str2: 
str0 = "aaa"
str1 = join(str0, "c") = "aaac"
str2 = join("aba", str1) = "abaaac"
It can be shown that the minimum possible length of str2 is 6.
 

 

Constraints:

  • 1 <= words.length <= 1000
  • 1 <= words[i].length <= 50
  • Each character in words[i] is an English lowercase letter

Solutions

Solution 1: Memoization Search

We notice that when concatenating strings, the first and last characters of the string will affect the length of the concatenated string. Therefore, we design a function $dfs(i, a, b)$, which represents the minimum length of the concatenated string starting from the $i$-th string, and the first character of the previously concatenated string is $a$, and the last character is $b$.

The execution process of the function $dfs(i, a, b)$ is as follows:

  • If $i = n$, it means that all strings have been concatenated, return $0$;
  • Otherwise, we consider concatenating the $i$-th string to the end or the beginning of the already concatenated string, and get the lengths $x$ and $y$ of the concatenated string, then $dfs(i, a, b) = \min(x, y) + |words[i]|$.

To avoid repeated calculations, we use the method of memoization search. Specifically, we use a three-dimensional array $f$ to store all the return values of $dfs(i, a, b)$. When we need to calculate $dfs(i, a, b)$, if $f[i][a][b]$ has been calculated, we directly return $f[i][a][b]$; otherwise, we calculate the value of $dfs(i, a, b)$ according to the above recurrence relation, and store it in $f[i][a][b]$.

In the main function, we directly return $|words[0]| + dfs(1, words[0][0], words[0][|words[0]| - 1])$.

The time complexity is $O(n \times C^2)$, and the space complexity is $O(n \times C^2)$. Where $C$ represents the maximum length of the string.

class Solution:
  def minimizeConcatenatedLength(self, words: List[str]) -> int:
    @cache
    def dfs(i: int, a: str, b: str) -> int:
      if i >= len(words):
        return 0
      s = words[i]
      x = dfs(i + 1, a, s[-1]) - int(s[0] == b)
      y = dfs(i + 1, s[0], b) - int(s[-1] == a)
      return len(s) + min(x, y)

    return len(words[0]) + dfs(1, words[0][0], words[0][-1])
class Solution {
  private Integer[][][] f;
  private String[] words;
  private int n;

  public int minimizeConcatenatedLength(String[] words) {
    n = words.length;
    this.words = words;
    f = new Integer[n][26][26];
    return words[0].length()
      + dfs(1, words[0].charAt(0) - 'a', words[0].charAt(words[0].length() - 1) - 'a');
  }

  private int dfs(int i, int a, int b) {
    if (i >= n) {
      return 0;
    }
    if (f[i][a][b] != null) {
      return f[i][a][b];
    }
    String s = words[i];
    int m = s.length();
    int x = dfs(i + 1, a, s.charAt(m - 1) - 'a') - (s.charAt(0) - 'a' == b ? 1 : 0);
    int y = dfs(i + 1, s.charAt(0) - 'a', b) - (s.charAt(m - 1) - 'a' == a ? 1 : 0);
    return f[i][a][b] = m + Math.min(x, y);
  }
}
class Solution {
public:
  int minimizeConcatenatedLength(vector<string>& words) {
    int n = words.size();
    int f[n][26][26];
    memset(f, 0, sizeof(f));
    function<int(int, int, int)> dfs = [&](int i, int a, int b) {
      if (i >= n) {
        return 0;
      }
      if (f[i][a][b]) {
        return f[i][a][b];
      }
      auto s = words[i];
      int m = s.size();
      int x = dfs(i + 1, a, s[m - 1] - 'a') - (s[0] - 'a' == b);
      int y = dfs(i + 1, s[0] - 'a', b) - (s[m - 1] - 'a' == a);
      return f[i][a][b] = m + min(x, y);
    };
    return words[0].size() + dfs(1, words[0].front() - 'a', words[0].back() - 'a');
  }
};
func minimizeConcatenatedLength(words []string) int {
  n := len(words)
  f := make([][26][26]int, n)
  var dfs func(i, a, b int) int
  dfs = func(i, a, b int) int {
    if i >= n {
      return 0
    }
    if f[i][a][b] > 0 {
      return f[i][a][b]
    }
    s := words[i]
    m := len(s)
    x := dfs(i+1, a, int(s[m-1]-'a'))
    y := dfs(i+1, int(s[0]-'a'), b)
    if int(s[0]-'a') == b {
      x--
    }
    if int(s[m-1]-'a') == a {
      y--
    }
    f[i][a][b] = m + min(x, y)
    return f[i][a][b]
  }
  return len(words[0]) + dfs(1, int(words[0][0]-'a'), int(words[0][len(words[0])-1]-'a'))
}
function minimizeConcatenatedLength(words: string[]): number {
  const n = words.length;
  const f: number[][][] = Array(n)
    .fill(0)
    .map(() =>
      Array(26)
        .fill(0)
        .map(() => Array(26).fill(0)),
    );
  const dfs = (i: number, a: number, b: number): number => {
    if (i >= n) {
      return 0;
    }
    if (f[i][a][b] > 0) {
      return f[i][a][b];
    }
    const s = words[i];
    const m = s.length;
    const x =
      dfs(i + 1, a, s[m - 1].charCodeAt(0) - 97) - (s[0].charCodeAt(0) - 97 === b ? 1 : 0);
    const y =
      dfs(i + 1, s[0].charCodeAt(0) - 97, b) - (s[m - 1].charCodeAt(0) - 97 === a ? 1 : 0);
    return (f[i][a][b] = Math.min(x + m, y + m));
  };
  return (
    words[0].length +
    dfs(1, words[0][0].charCodeAt(0) - 97, words[0][words[0].length - 1].charCodeAt(0) - 97)
  );
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文