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

📅  最后修改于: 2021-04-23 07:29:24             🧑  作者: 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


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


输出:

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)是(偶数,偶数,偶数)而(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

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


输出:

1

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