📌  相关文章
📜  重复替换两个不同的相邻字符串的最小长度字符串

📅  最后修改于: 2021-09-17 07:39:01             🧑  作者: Mango

给定一个由 ‘a’、’b’ 和 ‘c’ 三个字母组成的任意组合的字符串,找出通过重复应用以下操作可以获得的最小字符串的长度:

取任意两个相邻的不同字符并将它们替换为第三个。

例子:

Input : cab
Output : 2
We can select any two adjacent letters, 
say 'ca' and transform it into 'b', this 
leaves us with string 'bb' of length two.
    
Input : bcab
Output : 1
Selecting 'bc' and transforming it to 'a' 
leaves us with 'aab'. We can then select
'ab' and transform it to 'c', giving 'ac'. 
This can further be transformed into 'b',
which is of length one.

一种天真的方法是找到所有可能的替换,然后递归直到找到最小的字符串。这将需要指数级的时间。

引理:字母顺序不会影响最小字符串的长度或值。

归纳证明
基本情况:取字符串’ab’和’ba’,它们都减少到’c’

归纳假设:长度的所有字符串<= K减少到相同的字符串假设在每个字符串的每个字母的出现次数是相同的。

归纳步骤:取两个长度为 k + 1 且每个字母出现次数相同的字符串。找到一对相邻的字母

在两个字符串。这里会出现两种情况:

  1. 我们设法找到了这样一对字母。然后我们可以用第三个字母替换这些字母,从而得到两个长度为 k 的字符串,每个字母出现相同的次数,通过归纳假设将其简化为相同的字符串。即我们在两个字符串都有 ‘abcacb’ 和 ‘accbba’ 并减少了 ‘ac’,因此我们得到了 ‘abcbb’ 和 ‘bcbba’。
  2. 我们找不到这样的一对。当字符串中的所有字母都相同时,就会出现这种情况。在这种情况下,两个字符串本身是相同的,即 ‘ccccccc’ 和 ‘ccccccc’。

因此通过归纳,我们已经证明了这个引理。

动态规划方法
我们现在可以使用动态规划设计一个函数来解决这个问题。

C++
// C++ program to find smallest possible length
// of a string of only three characters
#include
using namespace std;
 
// Program to find length of reduced string
// in a string made of three characters.
#define MAX_LEN 110
 
// To store results of subproblems
int DP[MAX_LEN][MAX_LEN][MAX_LEN];
 
// A memoized function find result recursively.
// a, b and c are counts of 'a's, 'b's and
// 'c's in str
int length(int a, int b, int c)
{
    // If this subproblem is already evaluated
    if (DP[a][b] != -1)
        return DP[a][b];
 
    // If there is only one type of character
    if (a == 0 && b == 0)
        return (DP[a][b] = c);
    if (a == 0 && c == 0)
        return (DP[a][b] = b);
    if (b == 0 && c == 0)
        return (DP[a][b] = a);
 
    // If only two types of characters are present
    if (a == 0)
        return (DP[a][b] =
                    length(a + 1, b - 1, c - 1));
    if (b == 0)
        return (DP[a][b] =
                    length(a - 1, b + 1, c - 1));
    if (c == 0)
        return (DP[a][b] =
                    length(a - 1, b - 1, c + 1));
 
    // If all types of characters are present.
    // Try combining all pairs.
    return (DP[a][b] =
                min(length(a - 1, b - 1, c + 1),
                    min(length(a - 1, b + 1, c - 1),
                        length(a + 1, b - 1, c - 1))));
}
 
// Returns smallest possible length with given
// operation allowed.
int stringReduction(string str)
{
    int n = str.length();
 
    // Counting occurrences of three different
    // characters 'a', 'b' and 'c' in str
    int count[3] = {0};
    for (int i=0; i


Java
// Java program to find smallest possible length
// of a string of only three characters
import java.io.*;
class GFG
{
  static int MAX_LEN = 110;
 
  // Program to find length of reduced string
  // in a string made of three characters.
  static int[][][] DP = new int[MAX_LEN][MAX_LEN][MAX_LEN];
 
  // A memoized function find result recursively.
  // a, b and c are counts of 'a's, 'b's and
  // 'c's in str
  static int length(int a, int b, int c)
  {
 
    // If this subproblem is already
    // evaluated
    if(a < 0 || b < 0 || c < 0)
 
      // If this subproblem is already evaluated
      if (DP[a][b] != -1)
        return DP[a][b];
 
    // If there is only one type of character
    if (a == 0 && b == 0)
      return (DP[a][b] = c);
    if (a == 0 && c == 0)
      return (DP[a][b] = b);
    if (b == 0 && c == 0)
      return (DP[a][b] = a);
 
    // If only two types of characters are present
    if (a == 0)
      return (DP[a][b] =
              length(a + 1, b - 1, c - 1));
    if (b == 0)
      return (DP[a][b] =
              length(a - 1, b + 1, c - 1));
    if (c == 0)
      return (DP[a][b] =
              length(a - 1, b - 1, c + 1));
 
    // If all types of characters are present.
    // Try combining all pairs.
    DP[a][b] =
      Math.min(length(a - 1, b - 1, c + 1),
               Math.min(length(a - 1, b + 1, c - 1),
                        length(a + 1, b - 1, c - 1)));
 
    return DP[a][b];
  }
 
  // Returns smallest possible length with given
  // operation allowed.
  static int stringReduction(String str)
  {
    int n = str.length();
 
    // Counting occurrences of three different
    // characters 'a', 'b' and 'c' in str
    int[] count = new int[3];
    for (int i = 0; i < n; ++i)
      count[str.charAt(i) - 'a']++;
 
    // Initialize DP[][] entries as -1
    for (int i = 0; i <= count[0]; ++i)
      for (int j = 0; j < count[1]; ++j)
        for (int k = 0; k < count[2]; ++k)
          DP[i][j][k] = -1;
 
    return length(count[0], count[1], count[2]);
  }
 
  // Driver code
  public static void main (String[] args) {
    String str = "abcbbaacb";
    System.out.println(stringReduction(str));
  }
}
 
//  This code is contributed by rag2127


Python3
# Python3 program to find smallest possible
# length of a string of only three characters
 
# A memoized function find result recursively.
# a, b and c are counts of 'a's, 'b's and
# 'c's in str
def length(a, b, c):
     
    global DP
     
    #print(a, b, c)
     
    # If this subproblem is already
    # evaluated
    if a < 0 or b < 0 or c < 0:
        return 0
 
    if (DP[a][b] != -1):
        return DP[a][b]
 
    # If there is only one type
    # of character
    if (a == 0 and b == 0):
        DP[a][b] = c
        return c
    if (a == 0 and c == 0):
        DP[a][b] = b
        return b
    if (b == 0 and c == 0):
        DP[a][b] = a
        return a
 
    # If only two types of characters
    # are present
    if (a == 0):
        DP[a][b] = length(a + 1, b - 1,
                             c - 1)
        return DP[a][b]
         
    if (b == 0):
        DP[a][b] = length(a - 1, b + 1,
                             c - 1)
        return DP[a][b]
         
    if (c == 0):
        DP[a][b] = length(a - 1, b - 1,
                             c + 1)
        return DP[a][b]
 
    # If all types of characters are present.
    # Try combining all pairs.
    x = length(a - 1, b - 1, c + 1)
    y = length(a - 1, b + 1, c - 1)
    z = length(a + 1, b - 1, c - 1)
 
    DP[a][b] = min([x, y, z])
 
    return DP[a][b]
 
# Returns smallest possible length with
# given operation allowed.
def stringReduction(str):
     
    n = len(str)
 
    # Counting occurrences of three different
    # characters 'a', 'b' and 'c' in str
    count = [0] * 3
     
    for i in range(n):
        count[ord(str[i]) - ord('a')] += 1
 
    return length(count[0], count[1], count[2])
     
# Driver code
if __name__ == '__main__':
     
    DP = [[[-1 for i in range(110)]
               for i in range(110)]
               for i in range(110)]
 
    str = "abcbbaacb"
     
    print(stringReduction(str))
 
# This code is contributed by mohit kumar 29


C#
// C# program to find smallest possible length
// of a string of only three characters
using System;
public class GFG
{
 
  static int MAX_LEN = 110;
 
  // Program to find length of reduced string
  // in a string made of three characters.
  static int[,,] DP = new int[MAX_LEN, MAX_LEN, MAX_LEN];
 
  // A memoized function find result recursively.
  // a, b and c are counts of 'a's, 'b's and
  // 'c's in str
  static int length(int a, int b, int c)
  {
 
    // If this subproblem is already
    // evaluated
    if(a < 0 || b < 0 || c < 0)
 
      // If this subproblem is already evaluated
      if (DP[a, b, c] != -1)
        return DP[a, b, c];
 
    // If there is only one type of character
    if (a == 0 && b == 0)
      return (DP[a, b, c] = c);
    if (a == 0 && c == 0)
      return (DP[a, b, c] = b);
    if (b == 0 && c == 0)
      return (DP[a, b, c] = a);
 
    // If only two types of characters are present
    if (a == 0)
      return (DP[a, b, c] =
              length(a + 1, b - 1, c - 1));
    if (b == 0)
      return (DP[a, b, c] =
              length(a - 1, b + 1, c - 1));
    if (c == 0)
      return (DP[a, b, c] =
              length(a - 1, b - 1, c + 1));
 
    // If all types of characters are present.
    // Try combining all pairs.
    DP[a, b, c] =
      Math.Min(length(a - 1, b - 1, c + 1),
               Math.Min(length(a - 1, b + 1, c - 1),
                        length(a + 1, b - 1, c - 1)));
 
    return DP[a, b, c];
  }
 
  // Returns smallest possible length with given
  // operation allowed.
  static int stringReduction(string str)
  {
    int n = str.Length;
 
    // Counting occurrences of three different
    // characters 'a', 'b' and 'c' in str
    int[] count = new int[3];
    for (int i = 0; i < n; ++i)
      count[str[i] - 'a']++;
 
    // Initialize DP[][] entries as -1
    for (int i = 0; i <= count[0]; ++i)
      for (int j = 0; j < count[1]; ++j)
        for (int k = 0; k < count[2]; ++k)
          DP[i, j, k] = -1;
 
    return length(count[0], count[1], count[2]);
  }
 
  // Driver code
  static public void Main ()
  {
    string str = "abcbbaacb";
    Console.WriteLine(stringReduction(str));
  }
}
 
// This code is contributed by avanitrachhadiya2155


Javascript


C++
// C++ program to find smallest possible length
// of a string of only three characters
#include
using namespace std;
 
// Returns smallest possible length with given
// operation allowed.
int stringReduction(string str)
{
    int n = str.length();
 
    // Counint occurrences of three different
    // characters 'a', 'b' and 'c' in str
    int count[3] = {0};
    for (int i=0; i


Java
// Java program to find smallest possible length
// of a string of only three characters
public class GFG {
 
// Returns smallest possible length with given
// operation allowed.
    static int stringReduction(String str) {
        int n = str.length();
 
        // Counint occurrences of three different
        // characters 'a', 'b' and 'c' in str
        int count[] = new int[3];
        for (int i = 0; i < n; ++i) {
            count[str.charAt(i) - 'a']++;
        }
 
        // If all characters are same.
        if (count[0] == n || count[1] == n
                || count[2] == n) {
            return n;
        }
 
        // If all characters are present even number
        // of times or all are present odd number of
        // times.
        if ((count[0] % 2) == (count[1] % 2)
                && (count[1] % 2) == (count[2] % 2)) {
            return 2;
        }
 
        // Answer is 1 for all other cases.
        return 1;
    }
 
// Driver code
    public static void main(String[] args) {
        String str = "abcbbaacb";
        System.out.println(stringReduction(str));
    }
}
// This code is contributed by PrinciRaj1992


Python3
# Python3 program to find smallest possible
# length of a string of only three characters
 
# Returns smallest possible length
# with given operation allowed.
def stringReduction(str):
 
    n = len(str)
 
    # Counint occurrences of three different
    # characters 'a', 'b' and 'c' in str
    count = [0] * 3
    for i in range(n):
        count[ord(str[i]) - ord('a')] += 1
 
    # If all characters are same.
    if (count[0] == n or count[1] == n or
                         count[2] == n):
        return n
 
    # If all characters are present even number
    # of times or all are present odd number of
    # times.
    if ((count[0] % 2) == (count[1] % 2) and
        (count[1] % 2) == (count[2] % 2)):
        return 2
 
    # Answer is 1 for all other cases.
    return 1
 
# Driver code
if __name__ == "__main__":
     
    str = "abcbbaacb"
    print(stringReduction(str))
 
# This code is contributed by ita_c


C#
// C# program to find smallest possible length
// of a string of only three characters
using System;
public class GFG {
 
// Returns smallest possible length with given
// operation allowed.
    static int stringReduction(String str) {
        int n = str.Length;
 
        // Counint occurrences of three different
        // characters 'a', 'b' and 'c' in str
        int []count = new int[3];
        for (int i = 0; i < n; ++i) {
            count[str[i] - 'a']++;
        }
 
        // If all characters are same.
        if (count[0] == n || count[1] == n
                || count[2] == n) {
            return n;
        }
 
        // If all characters are present even number
        // of times or all are present odd number of
        // times.
        if ((count[0] % 2) == (count[1] % 2)
                && (count[1] % 2) == (count[2] % 2)) {
            return 2;
        }
 
        // Answer is 1 for all other cases.
        return 1;
    }
 
// Driver code
    public static void Main() {
        String str = "abcbbaacb";
        Console.WriteLine(stringReduction(str));
    }
}
// This code is contributed by 29AjayKumar


PHP


Javascript


输出:

1

在最坏的情况下,每个字母出现在整个字符串的1/3 中。这导致辅助空间 = O(N 3 ) 和时间复杂度 = O(N 3 )

Space Complexity = O(N^3)
Time Complexity = O(N^3)

数学方法
我们可以使用三个主要原则做得比这更好:

  1. 如果字符串不能进一步缩减,则字符串中的所有字母都相同。
  2. 最小字符串的长度是 <= 2 或等于原始字符串的长度,或者 2 < 最小字符串长度 < 原始字符串长度永远不会为真。
  3. 如果字符串的每个字母出现奇数次,经过一个缩减步骤后,它们都应出现偶数次。反之亦然,也就是说,如果字符串的每个字母出现偶数次,则在一个减少步骤后它们将出现奇数次。

这些可以证明如下:

  1. 如果存在任何两个不同的字母,我们可以选择它们并进一步减少字符串长度。
  2. 反证法:
    假设我们有长度的字符串,降低小于原来的字符串。例如’bbbbbbb’。那么这个字符串一定来自像’acbbbbbb’、’bbacbbbb’或任何其他类似组合的字符串。在这种情况下,我们可以选择 ‘bc’ 而不是 ‘ac’ 并进一步减少。
  3. 从上面的递归步骤中,我们将一个字母增加一个,并将其他两个字母减少一个。因此,如果我们有一个组合(奇数,奇数,奇数),那么它就会变成(奇数 + 1,奇数 – 1,奇数 – 1)或(偶数,偶数,偶数)。反面以类似的方式显示。

现在我们可以结合上述原则。
如果字符串由相同的字母重复组成,则其最小缩减字符串是其自身,length 是字符串的长度。
现在,其他可能的选项是减少一个或两个字符长度的字符串。现在,如果所有字符出现偶数次或奇数次,唯一可能的答案是 2,因为 (0, 2, 0) 是 (even, even, even) 而 (0, 1, 0) 是(偶数、奇数、偶数)所以只有 2 保留了这种偶数。
在任何其他条件下,答案变为 1。

C++

// C++ program to find smallest possible length
// of a string of only three characters
#include
using namespace std;
 
// Returns smallest possible length with given
// operation allowed.
int stringReduction(string str)
{
    int n = str.length();
 
    // Counint occurrences of three different
    // characters 'a', 'b' and 'c' in str
    int count[3] = {0};
    for (int i=0; i

Java

// Java program to find smallest possible length
// of a string of only three characters
public class GFG {
 
// Returns smallest possible length with given
// operation allowed.
    static int stringReduction(String str) {
        int n = str.length();
 
        // Counint occurrences of three different
        // characters 'a', 'b' and 'c' in str
        int count[] = new int[3];
        for (int i = 0; i < n; ++i) {
            count[str.charAt(i) - 'a']++;
        }
 
        // If all characters are same.
        if (count[0] == n || count[1] == n
                || count[2] == n) {
            return n;
        }
 
        // If all characters are present even number
        // of times or all are present odd number of
        // times.
        if ((count[0] % 2) == (count[1] % 2)
                && (count[1] % 2) == (count[2] % 2)) {
            return 2;
        }
 
        // Answer is 1 for all other cases.
        return 1;
    }
 
// Driver code
    public static void main(String[] args) {
        String str = "abcbbaacb";
        System.out.println(stringReduction(str));
    }
}
// This code is contributed by PrinciRaj1992

蟒蛇3

# Python3 program to find smallest possible
# length of a string of only three characters
 
# Returns smallest possible length
# with given operation allowed.
def stringReduction(str):
 
    n = len(str)
 
    # Counint occurrences of three different
    # characters 'a', 'b' and 'c' in str
    count = [0] * 3
    for i in range(n):
        count[ord(str[i]) - ord('a')] += 1
 
    # If all characters are same.
    if (count[0] == n or count[1] == n or
                         count[2] == n):
        return n
 
    # If all characters are present even number
    # of times or all are present odd number of
    # times.
    if ((count[0] % 2) == (count[1] % 2) and
        (count[1] % 2) == (count[2] % 2)):
        return 2
 
    # Answer is 1 for all other cases.
    return 1
 
# Driver code
if __name__ == "__main__":
     
    str = "abcbbaacb"
    print(stringReduction(str))
 
# This code is contributed by ita_c

C#

// C# program to find smallest possible length
// of a string of only three characters
using System;
public class GFG {
 
// Returns smallest possible length with given
// operation allowed.
    static int stringReduction(String str) {
        int n = str.Length;
 
        // Counint occurrences of three different
        // characters 'a', 'b' and 'c' in str
        int []count = new int[3];
        for (int i = 0; i < n; ++i) {
            count[str[i] - 'a']++;
        }
 
        // If all characters are same.
        if (count[0] == n || count[1] == n
                || count[2] == n) {
            return n;
        }
 
        // If all characters are present even number
        // of times or all are present odd number of
        // times.
        if ((count[0] % 2) == (count[1] % 2)
                && (count[1] % 2) == (count[2] % 2)) {
            return 2;
        }
 
        // Answer is 1 for all other cases.
        return 1;
    }
 
// Driver code
    public static void Main() {
        String str = "abcbbaacb";
        Console.WriteLine(stringReduction(str));
    }
}
// This code is contributed by 29AjayKumar

PHP


Javascript


输出:

1

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程