📜  回文分区 | DP-17

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

给定一个字符串,如果分区的每个子字符串都是回文,则字符串的分区是回文分区。例如,“aba|b|bbabb|a|b|aba”是“abbabbbabbababa”的回文分区。确定给定字符串的回文分区所需的最少切割。例如,“abbabbbabbababa”至少需要 3 次切割。三个切割是“a|babbbab|b|ababa”。如果字符串是回文,则至少需要 0 次切割。如果长度为 n 的字符串包含所有不同的字符,则需要最少 n-1 次切割。

回文分区

例子 :

这个问题是矩阵链乘法问题的一个变体。如果字符串是回文,那么我们简单地返回 0。否则,就像矩阵链乘法问题一样,我们尝试在所有可能的位置进行切割,递归计算每次切割的成本并返回最小值。
让给定的字符串是 str 并且 minPalPartion() 是返回回文分区所需的最少切割的函数。以下是最优子结构性质。

使用递归

// i is the starting index and j is the ending index. i must be passed as 0 and j as n-1
minPalPartion(str, i, j) = 0 if i == j. // When string is of length 1.
minPalPartion(str, i, j) = 0 if str[i..j] is palindrome.

// If none of the above conditions is true, then minPalPartion(str, i, j) can be 
// calculated recursively using the following formula.
minPalPartion(str, i, j) = Min { minPalPartion(str, i, k) + 1 +
                                 minPalPartion(str, k+1, j) } 
                           where k varies from i to j-1
C++
// C++ Code for Palindrome Partitioning
// Problem
#include 
using namespace std;
 
bool isPalindrome(string String, int i, int j)
{
    while(i < j)
    {
      if(String[i] != String[j])
        return false; 
      i++;
      j--;
    }
    return true;
}
int minPalPartion(string String, int i, int j)
{
    if( i >= j || isPalindrome(String, i, j) )
      return 0;
    int ans = INT_MAX, count;
    for(int k = i; k < j; k++)
    {
      count = minPalPartion(String, i, k) +
        minPalPartion(String, k + 1, j) + 1;
  
      ans = min(ans, count);
    }
    return ans;
}
// Driver code
int main() {
    string str = "ababbbabbababa";
    cout << "Min cuts needed for " <<
      "Palindrome Partitioning is " << 
      minPalPartion(str, 0, str.length() - 1) << endl;
    return 0;
}
// This code is contributed by rag2127


Java
// Java Code for Palindrome Partitioning
// Problem
public class GFG
{
 
  static boolean isPalindrome(String string, int i, int j)
  {
    while(i < j)
    {
      if(string.charAt(i) != string.charAt(j))
        return false; 
      i++;
      j--;
    }
    return true;
  }
 
  static int minPalPartion(String string, int i, int j)
  {   
    if( i >= j || isPalindrome(string, i, j) )
      return 0;
    int ans = Integer.MAX_VALUE, count;
    for(int k = i; k < j; k++)
    {
      count = minPalPartion(string, i, k) +
        minPalPartion(string, k + 1, j) + 1;
 
      ans = Math.min(ans, count);
    }
    return ans;
  }
 
  // Driver code
  public static void main(String args[])
  {
    String str = "ababbbabbababa";
    System.out.println("Min cuts needed for "
                       + "Palindrome Partitioning is " + minPalPartion(str, 0, str.length() - 1));
  }
}
 
// This code is contributed by adityapande88.


Python3
# Python code for implementation of Naive Recursive
# approach
def isPalindrome(x):
    return x == x[::-1]
 
 
def minPalPartion(string, i, j):
    if i >= j or isPalindrome(string[i:j + 1]):
        return 0
    ans = float('inf')
    for k in range(i, j):
        count = (
            1 + minPalPartion(string, i, k)
            + minPalPartion(string, k + 1, j)
        )
        ans = min(ans, count)
    return ans
 
 
def main():
    string = "ababbbabbababa"
     print(
     "Min cuts needed for Palindrome Partitioning is ",
     minPalPartion(string, 0, len(string) - 1),
    )
 
if __name__ == "__main__":
    main()
 
# This code is contributed by itsvinayak


C#
// C# Code for Palindrome Partitioning
// Problem
using System;
public class GFG
{
 
  static bool isPalindrome(string String, int i, int j)
  {
    while(i < j)
    {
      if(String[i] != String[j])
        return false; 
      i++;
      j--;
    }
    return true;
  }
 
  static int minPalPartion(string String, int i, int j)
  {   
    if( i >= j || isPalindrome(String, i, j) )
      return 0;
    int ans = Int32.MaxValue, count;
    for(int k = i; k < j; k++)
    {
      count = minPalPartion(String, i, k) +
        minPalPartion(String, k + 1, j) + 1;
 
      ans = Math.Min(ans, count);
    }
    return ans;
  }
 
  // Driver code
  static public void Main (){
    string str = "ababbbabbababa";
    Console.WriteLine("Min cuts needed for "+
                      "Palindrome Partitioning is " +
                      minPalPartion(str, 0, str.Length - 1));
  }
}
 
// This code is contributed by avanitrachhadiya2155


Javascript


C++
// Dynamic Programming Solution for
// Palindrome Partitioning Problem
#include 
using namespace std;
 
// Returns the minimum number of cuts
// needed to partition a string
// such that every part is a palindrome
int minPalPartion(string str)
{
    // Get the length of the string
    int n = str.length();
 
    /* Create two arrays to build the solution
       in bottom up manner
    C[i][j] = Minimum number of cuts needed for
              palindrome partitioning
              of substring str[i..j]
    P[i][j] = true if substring str[i..j] is
              palindrome, else false
    Note that C[i][j] is 0 if P[i][j] is true */
    int C[n][n];
    bool P[n][n];
 
    // Every substring of length 1 is a palindrome
    for (int i = 0; i < n; i++) {
        P[i][i] = true;
        C[i][i] = 0;
    }
 
    /* L is substring length. Build the
    solution in bottom up manner by
    considering all substrings of
    length starting from 2 to n.
    The loop structure is same as Matrix
    Chain Multiplication problem
    ( See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
    for (int L = 2; L <= n; L++) {
 
        // For substring of length L, set
        // different possible starting indexes
        for (int i = 0; i < n - L + 1; i++) {
            int j = i + L - 1; // Set ending index
 
            // If L is 2, then we just need to
            // compare two characters. Else
            // need to check two corner characters
            // and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1];
 
            // IF str[i..j] is palindrome, then C[i][j] is 0
            if (P[i][j] == true)
                C[i][j] = 0;
            else {
 
                // Make a cut at every possible
                // location starting from i to j,
                // and get the minimum cost cut.
                C[i][j] = INT_MAX;
                for (int k = i; k <= j - 1; k++)
                    C[i][j] = min(C[i][j], C[i][k] + C[k + 1][j] + 1);
            }
        }
    }
 
    // Return the min cut value for
    // complete string. i.e., str[0..n-1]
    return C[0][n - 1];
}
 
// Driver code
int main()
{
    string str = "ababbbabbababa";
    cout << "Min cuts needed for Palindrome"
            " Partitioning is "
         << minPalPartion(str);
    return 0;
}
 
// This code is contributed by rathbhupendra


C
// Dynamic Programming Solution for Palindrome Partitioning Problem
#include 
#include 
#include 
 
// A utility function to get minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
 
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minPalPartion(char* str)
{
    // Get the length of the string
    int n = strlen(str);
 
    /* Create two arrays to build the solution in bottom up manner
       C[i][j] = Minimum number of cuts needed for palindrome partitioning
                 of substring str[i..j]
       P[i][j] = true if substring str[i..j] is palindrome, else false
       Note that C[i][j] is 0 if P[i][j] is true */
    int C[n][n];
    bool P[n][n];
 
    int i, j, k, L; // different looping variables
 
    // Every substring of length 1 is a palindrome
    for (i = 0; i < n; i++) {
        P[i][i] = true;
        C[i][i] = 0;
    }
 
    /* L is substring length. Build the solution in bottom up manner by
       considering all substrings of length starting from 2 to n.
       The loop structure is same as Matrx Chain Multiplication problem (
       See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
    for (L = 2; L <= n; L++) {
        // For substring of length L, set different possible starting indexes
        for (i = 0; i < n - L + 1; i++) {
            j = i + L - 1; // Set ending index
 
            // If L is 2, then we just need to compare two characters. Else
            // need to check two corner characters and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1];
 
            // IF str[i..j] is palindrome, then C[i][j] is 0
            if (P[i][j] == true)
                C[i][j] = 0;
            else {
 
                // Make a cut at every possible location starting from i to j,
                // and get the minimum cost cut.
                C[i][j] = INT_MAX;
                for (k = i; k <= j - 1; k++)
                    C[i][j] = min(C[i][j], C[i][k] + C[k + 1][j] + 1);
            }
        }
    }
 
    // Return the min cut value for complete string. i.e., str[0..n-1]
    return C[0][n - 1];
}
 
// Driver program to test above function
int main()
{
    char str[] = "ababbbabbababa";
    printf("Min cuts needed for Palindrome Partitioning is %d",
           minPalPartion(str));
    return 0;
}


Java
// Java Code for Palindrome Partitioning
// Problem
public class GFG {
    // Returns the minimum number of cuts needed
    // to partition a string such that every
    // part is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.length();
 
        /* Create two arrays to build the solution
           in bottom up manner
           C[i][j] = Minimum number of cuts needed
                     for palindrome partitioning
                     of substring str[i..j]
           P[i][j] = true if substring str[i..j] is
                     palindrome, else false
           Note that C[i][j] is 0 if P[i][j] is
           true */
        int[][] C = new int[n][n];
        boolean[][] P = new boolean[n][n];
 
        int i, j, k, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i][i] = true;
            C[i][i] = 0;
        }
 
        /* L is substring length. Build the solution in
         bottom up manner by considering all substrings
         of length starting from 2 to n. The loop
         structure is same as Matrx Chain Multiplication
         problem (
        See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i][j] = (str.charAt(i) == str.charAt(j));
                else
                    P[i][j] = (str.charAt(i) == str.charAt(j)) && P[i + 1][j - 1];
 
                // IF str[i..j] is palindrome, then
                // C[i][j] is 0
                if (P[i][j] == true)
                    C[i][j] = 0;
                else {
                    // Make a cut at every possible
                    // localtion starting from i to j,
                    // and get the minimum cost cut.
                    C[i][j] = Integer.MAX_VALUE;
                    for (k = i; k <= j - 1; k++)
                        C[i][j] = Integer.min(C[i][j],
                                              C[i][k] + C[k + 1][j] + 1);
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[0][n - 1];
    }
 
    // Driver program to test above function
    public static void main(String args[])
    {
        String str = "ababbbabbababa";
        System.out.println("Min cuts needed for "
                           + "Palindrome Partitioning is " + minPalPartion(str));
    }
}
// This code is contributed by Sumit Ghosh


Python3
# Dynamic Programming Solution for
# Palindrome Partitioning Problem
 
# Returns the minimum number of
# cuts needed to partition a string
# such that every part is a palindrome
def minPalPartion(str):
     
    # Get the length of the string
    n = len(str)
     
    # Create two arrays to build the
    # solution in bottom up manner
    # C[i][j] = Minimum number of cuts
    # needed for palindrome
    # partitioning of substring str[i..j]
    # P[i][j] = true if substring str[i..j]
    # is palindrome, else false. Note that
    # C[i][j] is 0 if P[i][j] is true
    C = [[0 for i in range(n)]
            for i in range(n)]
    P = [[False for i in range(n)]
                for i in range(n)]
 
    # different looping variables
    j = 0
    k = 0
    L = 0
     
    # Every substring of length
    # 1 is a palindrome
    for i in range(n):
        P[i][i] = True;
        C[i][i] = 0;
         
    # L is substring length. Build the
    # solution in bottom-up manner by
    # considering all substrings of
    # length starting from 2 to n.
    # The loop structure is the same as
    # Matrix Chain Multiplication problem 
    # (See https://www.geeksforgeeks.org / matrix-chain-multiplication-dp-8/ )
    for L in range(2, n + 1):
         
        # For substring of length L, set
        # different possible starting indexes
        for i in range(n - L + 1):
            j = i + L - 1 # Set ending index
             
            # If L is 2, then we just need to
            # compare two characters. Else
            # need to check two corner characters
            # and value of P[i + 1][j-1]
            if L == 2:
                P[i][j] = (str[i] == str[j])
            else:
                P[i][j] = ((str[i] == str[j]) and
                             P[i + 1][j - 1])
                              
            # IF str[i..j] is palindrome,
            # then C[i][j] is 0
            if P[i][j] == True:
                C[i][j] = 0
            else:
                 
                # Make a cut at every possible
                # location starting from i to j,
                # and get the minimum cost cut.
                C[i][j] = 100000000
                for k in range(i, j):
                    C[i][j] = min (C[i][j], C[i][k] +
                                   C[k + 1][j] + 1)
                                    
    # Return the min cut value for
    # complete string. i.e., str[0..n-1]
    return C[0][n - 1]
 
# Driver code
str = "ababbbabbababa"
print ('Min cuts needed for Palindrome Partitioning is',
                                     minPalPartion(str))
                                       
# This code is contributed
# by Sahil shelangia


C#
// C# Code for Palindrome Partitioning
// Problem
using System;
 
class GFG {
    // Returns the minimum number of cuts needed
    // to partition a string such that every
    // part is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.Length;
 
        /* Create two arrays to build the solution
        in bottom up manner
        C[i][j] = Minimum number of cuts needed
                    for palindrome partitioning
                    of substring str[i..j]
        P[i][j] = true if substring str[i..j] is
                    palindrome, else false
        Note that C[i][j] is 0 if P[i][j] is
        true */
        int[, ] C = new int[n, n];
        bool[, ] P = new bool[n, n];
 
        int i, j, k, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i, i] = true;
            C[i, i] = 0;
        }
 
        /* L is substring length. Build the solution in
        bottom up manner by considering all substrings
        of length starting from 2 to n. The loop
        structure is same as Matrx Chain Multiplication
        problem (
        See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i, j] = (str[i] == str[j]);
                else
                    P[i, j] = (str[i] == str[j]) && P[i + 1, j - 1];
 
                // IF str[i..j] is palindrome, then
                // C[i][j] is 0
                if (P[i, j] == true)
                    C[i, j] = 0;
                else {
                    // Make a cut at every possible
                    // localtion starting from i to j,
                    // and get the minimum cost cut.
                    C[i, j] = int.MaxValue;
                    for (k = i; k <= j - 1; k++)
                        C[i, j] = Math.Min(C[i, j], C[i, k]
                                                        + C[k + 1, j] + 1);
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[0, n - 1];
    }
 
    // Driver program
    public static void Main()
    {
        String str = "ababbbabbababa";
        Console.Write("Min cuts needed for "
                      + "Palindrome Partitioning is " + minPalPartion(str));
    }
}
 
// This code is contributed by Sam007


PHP


C++
#include 
using namespace std;
 
int minCut(string a)
{
    int cut[a.length()];
    bool palindrome[a.length()][a.length()];
    memset(palindrome, false, sizeof(palindrome));
    for (int i = 0; i < a.length(); i++)
    {
        int minCut = i;
        for (int j = 0; j <= i; j++)
        {
            if (a[i] == a[j] && (i - j < 2 || palindrome[j + 1][i - 1]))
            {
                palindrome[j][i] = true;
                minCut = min(minCut, j == 0 ? 0 : (cut[j - 1] + 1));
            }
        }
        cut[i] = minCut;
    }
    return cut[a.length() - 1];
}
 
// Driver code
int main()
{
    cout << minCut("aab") << endl;
    cout << minCut("aabababaxx") << endl;
    return 0;
}
 
// This code is contributed by divyesh072019.


Java
import java.io.*;
 
class GFG {
 
    public static int minCut(String a)
    {
        int[] cut = new int[a.length()];
        boolean[][] palindrome = new boolean[a.length()][a.length()];
 
        for (int i = 0; i < a.length(); i++) {
            int minCut = i;
            for (int j = 0; j <= i; j++) {
                if (a.charAt(i) == a.charAt(j) && (i - j < 2 || palindrome[j + 1][i - 1])) {
                    palindrome[j][i] = true;
                    minCut = Math.min(minCut, j == 0 ? 0 : (cut[j - 1] + 1));
                }
            }
            cut[i] = minCut;
        }
 
        return cut[a.length() - 1];
    }
 
    public static void main(String[] args)
    {
        System.out.println(minCut("aab"));
        System.out.println(minCut("aabababaxx"));
    }
}


Python3
def minCut(a):
 
    cut = [0 for i in range(len(a))]
    palindrome = [[False for i in range(len(a))] for j in range(len(a))]
    for i in range(len(a)):
        minCut = i;
        for j in range(i + 1):
            if (a[i] == a[j] and (i - j < 2 or palindrome[j + 1][i - 1])):      
                palindrome[j][i] = True;
                minCut = min(minCut,0 if  j == 0 else (cut[j - 1] + 1));
        cut[i] = minCut;  
    return cut[len(a) - 1];
 
# Driver code
if __name__=='__main__':
 
    print(minCut("aab"))
    print(minCut("aabababaxx"))
     
    # This code is contributed by rutvik_56


C#
using System;
using System.Collections.Generic;  
class GFG
{  
    static int minCut(string a)
    {
        int[] cut = new int[a.Length];
        bool[,] palindrome = new bool[a.Length, a.Length];  
        for (int i = 0; i < a.Length; i++)
        {
            int minCut = i;
            for (int j = 0; j <= i; j++)
            {
                if (a[i] == a[j] && (i - j < 2 ||
                                     palindrome[j + 1, i - 1]))
                {
                    palindrome[j, i] = true;
                    minCut = Math.Min(minCut, j == 0 ? 0 : (cut[j - 1] + 1));
                }
            }
            cut[i] = minCut;
        }
        return cut[a.Length - 1];
    }
   
  // Driver code       
  static void Main()
  {
    Console.WriteLine(minCut("aab"));
    Console.WriteLine(minCut("aabababaxx"));
  }
}
 
// This code is contributed by divyeshrabadiya07.


C++
// Dynamic Programming Solution for Palindrome Partitioning Problem
#include 
#include 
#include 
 
// A utility function to get minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
 
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minPalPartion(char* str)
{
    // Get the length of the string
    int n = strlen(str);
 
    /* Create two arrays to build the solution in bottom-up manner
       C[i] = Minimum number of cuts needed for a palindrome partitioning
                 of substring str[0..i]
       P[i][j] = true if substring str[i..j] is palindrome, else false
       Note that C[i] is 0 if P[0][i] is true */
    int C[n];
    bool P[n][n];
 
    int i, j, k, L; // different looping variables
 
    // Every substring of length 1 is a palindrome
    for (i = 0; i < n; i++) {
        P[i][i] = true;
    }
 
    /* L is substring length. Build the solution in bottom up manner by
       considering all substrings of length starting from 2 to n. */
    for (L = 2; L <= n; L++) {
        // For substring of length L, set different possible starting indexes
        for (i = 0; i < n - L + 1; i++) {
            j = i + L - 1; // Set ending index
 
            // If L is 2, then we just need to compare two characters. Else
            // need to check two corner characters and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1];
        }
    }
 
    for (i = 0; i < n; i++) {
        if (P[0][i] == true)
            C[i] = 0;
        else {
            C[i] = INT_MAX;
            for (j = 0; j < i; j++) {
                if (P[j + 1][i] == true && 1 + C[j] < C[i])
                    C[i] = 1 + C[j];
            }
        }
    }
 
    // Return the min cut value for complete string. i.e., str[0..n-1]
    return C[n - 1];
}
 
// Driver program to test above function
int main()
{
    char str[] = "ababbbabbababa";
    printf("Min cuts needed for Palindrome Partitioning is %d",
           minPalPartion(str));
    return 0;
}


Java
// Java Code for Palindrome Partitioning
// Problem
public class GFG {
    // Returns the minimum number of cuts needed
    // to partition a string such that every part
    // is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.length();
 
        /* Create two arrays to build the solution
        in bottom up manner
           C[i] = Minimum number of cuts needed for
           palindrome partitioning of substring
           str[0..i]
           P[i][j] = true if substring str[i..j] is
           palindrome, else false
           Note that C[i] is 0 if P[0][i] is true */
        int[] C = new int[n];
        boolean[][] P = new boolean[n][n];
 
        int i, j, k, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i][i] = true;
        }
 
        /* L is substring length. Build the solution
        in bottom up manner by considering all substrings
        of length starting from 2 to n. */
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i][j] = (str.charAt(i) == str.charAt(j));
                else
                    P[i][j] = (str.charAt(i) == str.charAt(j)) && P[i + 1][j - 1];
            }
        }
 
        for (i = 0; i < n; i++) {
            if (P[0][i] == true)
                C[i] = 0;
            else {
                C[i] = Integer.MAX_VALUE;
                for (j = 0; j < i; j++) {
                    if (P[j + 1][i] == true && 1 + C[j] < C[i])
                        C[i] = 1 + C[j];
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[n - 1];
    }
 
    // Driver program to test above function
    public static void main(String args[])
    {
        String str = "ababbbabbababa";
        System.out.println("Min cuts needed for "
                           + "Palindrome Partitioning"
                           + " is " + minPalPartion(str));
    }
}
// This code is contributed by Sumit Ghosh


Python3
# Dynamic Programming Solution for
# Palindrome Partitioning Problem
import sys
 
# Returns the minimum number of cuts
# needed to partition a string such
# that every part is a palindrome
def minPalPartion(str1):
     
    # Get the length of the string
    n = len(str1);
     
    # Create two arrays to build the solution
    # in bottom up manner
    # C[i] = Minimum number of cuts needed
    # for palindrome partitioning of
    # substring str[0..i]
    # P[i][j] = true if substring str[i..j]
    # is palindrome, else false
    # Note that C[i] is 0 if P[0][i] is true
    C = [0]*(n + 1);
    P = [[False for x in range(n + 1)] for y in range(n + 1)];
     
    # Every substring of length 1 is
    # a palindrome
    for i in range(n):
        P[i][i] = True;
     
    # L is substring length. Build the solution
    # in bottom up manner by considering all
    # substrings of length starting from 2 to n.
    for L in range(2, n + 1):
         
        # For substring of length L, set
        # different possible starting indexes
        for i in range(n - L + 1):
            j = i + L - 1;
             
            # Set ending index
            # If L is 2, then we just need to
            # compare two characters. Else need
            # to check two corner characters and
            # value of P[i + 1][j-1]
            if (L == 2):
                P[i][j] = (str1[i] == str1[j]);
            else:
                P[i][j] = ((str1[i] == str1[j]) and P[i + 1][j - 1]);
    for i in range(n):
        if (P[0][i] == True):
            C[i] = 0;
        else:
            C[i] = sys.maxsize;
            for j in range(i):
                if(P[j + 1][i] == True and 1 + C[j] < C[i]):
                    C[i] = 1 + C[j];
     
    # Return the min cut value for complete
    # string. i.e., str[0..n-1]
    return C[n - 1];
 
# Driver Code
str1 = "ababbbabbababa";
print("Min cuts needed for Palindrome Partitioning is", minPalPartion(str1));
 
# This code is contributed by mits


C#
// C# Code for Palindrome Partitioning
// Problem
using System;
 
class GFG {
 
    // Returns the minimum number of cuts needed
    // to partition a string such that every part
    // is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.Length;
 
        /* Create two arrays to build the solution
        in bottom up manner
        C[i] = Minimum number of cuts needed for
        palindrome partitioning of substring
        str[0..i]
        P[i][j] = true if substring str[i..j] is
        palindrome, else false
        Note that C[i] is 0 if P[0][i] is true */
        int[] C = new int[n];
        bool[, ] P = new bool[n, n];
 
        int i, j, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i, i] = true;
        }
 
        /* L is substring length. Build the solution
        in bottom up manner by considering all substrings
        of length starting from 2 to n. */
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i, j] = (str[i] == str[j]);
                else
                    P[i, j] = (str[i] == str[j]) && P[i + 1, j - 1];
            }
        }
 
        for (i = 0; i < n; i++) {
            if (P[0, i] == true)
                C[i] = 0;
            else {
                C[i] = int.MaxValue;
                for (j = 0; j < i; j++) {
                    if (P[j + 1, i] == true && 1 + C[j] < C[i])
                        C[i] = 1 + C[j];
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[n - 1];
    }
 
    // Driver program
    public static void Main()
    {
        String str = "ababbbabbababa";
        Console.Write("Min cuts needed for "
                      + "Palindrome Partitioning"
                      + " is " + minPalPartion(str));
    }
}
 
// This code is contributed by Sam007


PHP


C++
// Using memoizatoin to solve the partition problem.
#include 
using namespace std;
// Function to check if input string is pallindrome or not
bool ispallindrome(string input, int start, int end)
{
    // Using two pointer technique to check pallindrome
    while (start < end) {
        if (input[start] != input[end])
            return false;
        start++;
        end--;
    }
    return true;
}
 
// Function to find keys for the Hashmap
string convert(int a, int b)
{
    return to_string(a) + "" + to_string(b);
}
 
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minpalparti_memo(string input, int i, int j, unordered_map& memo)
{
    if (i > j)
        return 0;
    // Key for the Input String
    string ij = convert(i, j);
 
    // If the no of partitions for string "ij" is already calculated
    // then return the calculated value using the Hashmap
    if (memo.find(ij) != memo.end()) {
        return memo[ij];
    }
    // Every String of length 1 is a pallindrome
    if (i == j) {
        memo[ij] = 0;
        return 0;
    }
    if (ispallindrome(input, i, j)) {
        memo[ij] = 0;
        return 0;
    }
    int minimum = INT_MAX;
    // Make a cut at every possible location starting from i to j
    for (int k = i; k < j; k++) {
        int left_min = INT_MAX;
        int right_min = INT_MAX;
        string left = convert(i, k);
        string right = convert(k + 1, j);
 
        // If left cut is found already
        if (memo.find(left) != memo.end()) {
            left_min = memo[left];
        }
        // If right cut is found already
        if (memo.find(right) != memo.end()) {
            right_min = memo[right];
        }
 
        // Recursively calculating for left and right strings
        if (left_min == INT_MAX)
            left_min = minpalparti_memo(input, i, k, memo);
        if (right_min == INT_MAX)
            right_min = minpalparti_memo(input, k + 1, j, memo);
 
        // Taking minimum of all k possible cuts
        minimum = min(minimum, left_min + 1 + right_min);
    }
 
    memo[ij] = minimum;
    // Return the min cut value for complete string.
    return memo[ij];
}
int main()
{
    string input = "ababbbabbababa";
    unordered_map memo;
    cout << minpalparti_memo(input, 0, input.length() - 1, memo) << endl;
    return 0;
}


Python3
# Using memoizatoin to solve the partition problem.
 
# Function to check if input string is pallindrome or not
def ispallindrome(input, start, end):
 
    # Using two pointer technique to check pallindrome
    while (start < end):
        if (input[start] != input[end]):
            return False;
        start += 1
        end -= 1
    return True;
 
# Function to find keys for the Hashmap
def convert(a, b):
    return str(a) + str(b);
 
# Returns the minimum number of cuts needed to partition a string
# such that every part is a palindrome
def minpalparti_memo(input, i, j, memo):
 
    if (i > j):
        return 0;
       
    # Key for the Input String
    ij = convert(i, j);
 
    # If the no of partitions for string "ij" is already calculated
    # then return the calculated value using the Hashmap
    if (ij in memo):
        return memo[ij];
     
    # Every String of length 1 is a pallindrome
    if (i == j):
        memo[ij] = 0;
        return 0;
    if (ispallindrome(input, i, j)):
        memo[ij] = 0;
        return 0;  
    minimum = 1000000000
     
    # Make a cut at every possible location starting from i to j
    for k in range(i, j):
        left_min = 1000000000
        right_min = 1000000000
        left = convert(i, k);
        right = convert(k + 1, j);
 
        # If left cut is found already
        if (left in memo):
            left_min = memo[left];
         
        # If right cut is found already
        if (right in memo):
            right_min = memo[right];
         
        # Recursively calculating for left and right strings
        if (left_min == 1000000000):
            left_min = minpalparti_memo(input, i, k, memo);
        if (right_min == 1000000000):
            right_min = minpalparti_memo(input, k + 1, j, memo);
 
        # Taking minimum of all k possible cuts
        minimum = min(minimum, left_min + 1 + right_min);
    memo[ij] = minimum;
     
    # Return the min cut value for complete string.
    return memo[ij];
 
  # Driver code
if __name__=='__main__':
 
    input = "ababbbabbababa";
    memo = dict()
    print(minpalparti_memo(input, 0, len(input) - 1, memo))
     
# This code is contributed by Pratham76.


输出:

Min cuts needed for Palindrome Partitioning is 3 

使用动态规划:
以下是动态规划解决方案。它将子问题的解存储在两个数组 P[][] 和 C[][] 中,并重新使用计算值。

C++

// Dynamic Programming Solution for
// Palindrome Partitioning Problem
#include 
using namespace std;
 
// Returns the minimum number of cuts
// needed to partition a string
// such that every part is a palindrome
int minPalPartion(string str)
{
    // Get the length of the string
    int n = str.length();
 
    /* Create two arrays to build the solution
       in bottom up manner
    C[i][j] = Minimum number of cuts needed for
              palindrome partitioning
              of substring str[i..j]
    P[i][j] = true if substring str[i..j] is
              palindrome, else false
    Note that C[i][j] is 0 if P[i][j] is true */
    int C[n][n];
    bool P[n][n];
 
    // Every substring of length 1 is a palindrome
    for (int i = 0; i < n; i++) {
        P[i][i] = true;
        C[i][i] = 0;
    }
 
    /* L is substring length. Build the
    solution in bottom up manner by
    considering all substrings of
    length starting from 2 to n.
    The loop structure is same as Matrix
    Chain Multiplication problem
    ( See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
    for (int L = 2; L <= n; L++) {
 
        // For substring of length L, set
        // different possible starting indexes
        for (int i = 0; i < n - L + 1; i++) {
            int j = i + L - 1; // Set ending index
 
            // If L is 2, then we just need to
            // compare two characters. Else
            // need to check two corner characters
            // and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1];
 
            // IF str[i..j] is palindrome, then C[i][j] is 0
            if (P[i][j] == true)
                C[i][j] = 0;
            else {
 
                // Make a cut at every possible
                // location starting from i to j,
                // and get the minimum cost cut.
                C[i][j] = INT_MAX;
                for (int k = i; k <= j - 1; k++)
                    C[i][j] = min(C[i][j], C[i][k] + C[k + 1][j] + 1);
            }
        }
    }
 
    // Return the min cut value for
    // complete string. i.e., str[0..n-1]
    return C[0][n - 1];
}
 
// Driver code
int main()
{
    string str = "ababbbabbababa";
    cout << "Min cuts needed for Palindrome"
            " Partitioning is "
         << minPalPartion(str);
    return 0;
}
 
// This code is contributed by rathbhupendra

C

// Dynamic Programming Solution for Palindrome Partitioning Problem
#include 
#include 
#include 
 
// A utility function to get minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
 
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minPalPartion(char* str)
{
    // Get the length of the string
    int n = strlen(str);
 
    /* Create two arrays to build the solution in bottom up manner
       C[i][j] = Minimum number of cuts needed for palindrome partitioning
                 of substring str[i..j]
       P[i][j] = true if substring str[i..j] is palindrome, else false
       Note that C[i][j] is 0 if P[i][j] is true */
    int C[n][n];
    bool P[n][n];
 
    int i, j, k, L; // different looping variables
 
    // Every substring of length 1 is a palindrome
    for (i = 0; i < n; i++) {
        P[i][i] = true;
        C[i][i] = 0;
    }
 
    /* L is substring length. Build the solution in bottom up manner by
       considering all substrings of length starting from 2 to n.
       The loop structure is same as Matrx Chain Multiplication problem (
       See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
    for (L = 2; L <= n; L++) {
        // For substring of length L, set different possible starting indexes
        for (i = 0; i < n - L + 1; i++) {
            j = i + L - 1; // Set ending index
 
            // If L is 2, then we just need to compare two characters. Else
            // need to check two corner characters and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1];
 
            // IF str[i..j] is palindrome, then C[i][j] is 0
            if (P[i][j] == true)
                C[i][j] = 0;
            else {
 
                // Make a cut at every possible location starting from i to j,
                // and get the minimum cost cut.
                C[i][j] = INT_MAX;
                for (k = i; k <= j - 1; k++)
                    C[i][j] = min(C[i][j], C[i][k] + C[k + 1][j] + 1);
            }
        }
    }
 
    // Return the min cut value for complete string. i.e., str[0..n-1]
    return C[0][n - 1];
}
 
// Driver program to test above function
int main()
{
    char str[] = "ababbbabbababa";
    printf("Min cuts needed for Palindrome Partitioning is %d",
           minPalPartion(str));
    return 0;
}

Java

// Java Code for Palindrome Partitioning
// Problem
public class GFG {
    // Returns the minimum number of cuts needed
    // to partition a string such that every
    // part is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.length();
 
        /* Create two arrays to build the solution
           in bottom up manner
           C[i][j] = Minimum number of cuts needed
                     for palindrome partitioning
                     of substring str[i..j]
           P[i][j] = true if substring str[i..j] is
                     palindrome, else false
           Note that C[i][j] is 0 if P[i][j] is
           true */
        int[][] C = new int[n][n];
        boolean[][] P = new boolean[n][n];
 
        int i, j, k, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i][i] = true;
            C[i][i] = 0;
        }
 
        /* L is substring length. Build the solution in
         bottom up manner by considering all substrings
         of length starting from 2 to n. The loop
         structure is same as Matrx Chain Multiplication
         problem (
        See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i][j] = (str.charAt(i) == str.charAt(j));
                else
                    P[i][j] = (str.charAt(i) == str.charAt(j)) && P[i + 1][j - 1];
 
                // IF str[i..j] is palindrome, then
                // C[i][j] is 0
                if (P[i][j] == true)
                    C[i][j] = 0;
                else {
                    // Make a cut at every possible
                    // localtion starting from i to j,
                    // and get the minimum cost cut.
                    C[i][j] = Integer.MAX_VALUE;
                    for (k = i; k <= j - 1; k++)
                        C[i][j] = Integer.min(C[i][j],
                                              C[i][k] + C[k + 1][j] + 1);
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[0][n - 1];
    }
 
    // Driver program to test above function
    public static void main(String args[])
    {
        String str = "ababbbabbababa";
        System.out.println("Min cuts needed for "
                           + "Palindrome Partitioning is " + minPalPartion(str));
    }
}
// This code is contributed by Sumit Ghosh

蟒蛇3

# Dynamic Programming Solution for
# Palindrome Partitioning Problem
 
# Returns the minimum number of
# cuts needed to partition a string
# such that every part is a palindrome
def minPalPartion(str):
     
    # Get the length of the string
    n = len(str)
     
    # Create two arrays to build the
    # solution in bottom up manner
    # C[i][j] = Minimum number of cuts
    # needed for palindrome
    # partitioning of substring str[i..j]
    # P[i][j] = true if substring str[i..j]
    # is palindrome, else false. Note that
    # C[i][j] is 0 if P[i][j] is true
    C = [[0 for i in range(n)]
            for i in range(n)]
    P = [[False for i in range(n)]
                for i in range(n)]
 
    # different looping variables
    j = 0
    k = 0
    L = 0
     
    # Every substring of length
    # 1 is a palindrome
    for i in range(n):
        P[i][i] = True;
        C[i][i] = 0;
         
    # L is substring length. Build the
    # solution in bottom-up manner by
    # considering all substrings of
    # length starting from 2 to n.
    # The loop structure is the same as
    # Matrix Chain Multiplication problem 
    # (See https://www.geeksforgeeks.org / matrix-chain-multiplication-dp-8/ )
    for L in range(2, n + 1):
         
        # For substring of length L, set
        # different possible starting indexes
        for i in range(n - L + 1):
            j = i + L - 1 # Set ending index
             
            # If L is 2, then we just need to
            # compare two characters. Else
            # need to check two corner characters
            # and value of P[i + 1][j-1]
            if L == 2:
                P[i][j] = (str[i] == str[j])
            else:
                P[i][j] = ((str[i] == str[j]) and
                             P[i + 1][j - 1])
                              
            # IF str[i..j] is palindrome,
            # then C[i][j] is 0
            if P[i][j] == True:
                C[i][j] = 0
            else:
                 
                # Make a cut at every possible
                # location starting from i to j,
                # and get the minimum cost cut.
                C[i][j] = 100000000
                for k in range(i, j):
                    C[i][j] = min (C[i][j], C[i][k] +
                                   C[k + 1][j] + 1)
                                    
    # Return the min cut value for
    # complete string. i.e., str[0..n-1]
    return C[0][n - 1]
 
# Driver code
str = "ababbbabbababa"
print ('Min cuts needed for Palindrome Partitioning is',
                                     minPalPartion(str))
                                       
# This code is contributed
# by Sahil shelangia

C#

// C# Code for Palindrome Partitioning
// Problem
using System;
 
class GFG {
    // Returns the minimum number of cuts needed
    // to partition a string such that every
    // part is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.Length;
 
        /* Create two arrays to build the solution
        in bottom up manner
        C[i][j] = Minimum number of cuts needed
                    for palindrome partitioning
                    of substring str[i..j]
        P[i][j] = true if substring str[i..j] is
                    palindrome, else false
        Note that C[i][j] is 0 if P[i][j] is
        true */
        int[, ] C = new int[n, n];
        bool[, ] P = new bool[n, n];
 
        int i, j, k, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i, i] = true;
            C[i, i] = 0;
        }
 
        /* L is substring length. Build the solution in
        bottom up manner by considering all substrings
        of length starting from 2 to n. The loop
        structure is same as Matrx Chain Multiplication
        problem (
        See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i, j] = (str[i] == str[j]);
                else
                    P[i, j] = (str[i] == str[j]) && P[i + 1, j - 1];
 
                // IF str[i..j] is palindrome, then
                // C[i][j] is 0
                if (P[i, j] == true)
                    C[i, j] = 0;
                else {
                    // Make a cut at every possible
                    // localtion starting from i to j,
                    // and get the minimum cost cut.
                    C[i, j] = int.MaxValue;
                    for (k = i; k <= j - 1; k++)
                        C[i, j] = Math.Min(C[i, j], C[i, k]
                                                        + C[k + 1, j] + 1);
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[0, n - 1];
    }
 
    // Driver program
    public static void Main()
    {
        String str = "ababbbabbababa";
        Console.Write("Min cuts needed for "
                      + "Palindrome Partitioning is " + minPalPartion(str));
    }
}
 
// This code is contributed by Sam007

PHP


输出:

Min cuts needed for Palindrome Partitioning is 3 

时间复杂度: O(n 3 )

我们可以进一步优化上面的代码。我们可以用 P[i] 本身来代替在 O(n^2) 中单独计算 C[i]。下面是这个问题的高度优化代码:

C++

#include 
using namespace std;
 
int minCut(string a)
{
    int cut[a.length()];
    bool palindrome[a.length()][a.length()];
    memset(palindrome, false, sizeof(palindrome));
    for (int i = 0; i < a.length(); i++)
    {
        int minCut = i;
        for (int j = 0; j <= i; j++)
        {
            if (a[i] == a[j] && (i - j < 2 || palindrome[j + 1][i - 1]))
            {
                palindrome[j][i] = true;
                minCut = min(minCut, j == 0 ? 0 : (cut[j - 1] + 1));
            }
        }
        cut[i] = minCut;
    }
    return cut[a.length() - 1];
}
 
// Driver code
int main()
{
    cout << minCut("aab") << endl;
    cout << minCut("aabababaxx") << endl;
    return 0;
}
 
// This code is contributed by divyesh072019.

Java

import java.io.*;
 
class GFG {
 
    public static int minCut(String a)
    {
        int[] cut = new int[a.length()];
        boolean[][] palindrome = new boolean[a.length()][a.length()];
 
        for (int i = 0; i < a.length(); i++) {
            int minCut = i;
            for (int j = 0; j <= i; j++) {
                if (a.charAt(i) == a.charAt(j) && (i - j < 2 || palindrome[j + 1][i - 1])) {
                    palindrome[j][i] = true;
                    minCut = Math.min(minCut, j == 0 ? 0 : (cut[j - 1] + 1));
                }
            }
            cut[i] = minCut;
        }
 
        return cut[a.length() - 1];
    }
 
    public static void main(String[] args)
    {
        System.out.println(minCut("aab"));
        System.out.println(minCut("aabababaxx"));
    }
}

蟒蛇3

def minCut(a):
 
    cut = [0 for i in range(len(a))]
    palindrome = [[False for i in range(len(a))] for j in range(len(a))]
    for i in range(len(a)):
        minCut = i;
        for j in range(i + 1):
            if (a[i] == a[j] and (i - j < 2 or palindrome[j + 1][i - 1])):      
                palindrome[j][i] = True;
                minCut = min(minCut,0 if  j == 0 else (cut[j - 1] + 1));
        cut[i] = minCut;  
    return cut[len(a) - 1];
 
# Driver code
if __name__=='__main__':
 
    print(minCut("aab"))
    print(minCut("aabababaxx"))
     
    # This code is contributed by rutvik_56

C#

using System;
using System.Collections.Generic;  
class GFG
{  
    static int minCut(string a)
    {
        int[] cut = new int[a.Length];
        bool[,] palindrome = new bool[a.Length, a.Length];  
        for (int i = 0; i < a.Length; i++)
        {
            int minCut = i;
            for (int j = 0; j <= i; j++)
            {
                if (a[i] == a[j] && (i - j < 2 ||
                                     palindrome[j + 1, i - 1]))
                {
                    palindrome[j, i] = true;
                    minCut = Math.Min(minCut, j == 0 ? 0 : (cut[j - 1] + 1));
                }
            }
            cut[i] = minCut;
        }
        return cut[a.Length - 1];
    }
   
  // Driver code       
  static void Main()
  {
    Console.WriteLine(minCut("aab"));
    Console.WriteLine(minCut("aabababaxx"));
  }
}
 
// This code is contributed by divyeshrabadiya07.

对上述方法的优化
在上面的方法中,我们可以在找到所有回文子串的同时计算最小割。如果我们找到所有回文子串 1 st然后我们计算最小割,时间复杂度将减少到 O(n 2 )。
感谢Vivek提出此优化建议。

C++

// Dynamic Programming Solution for Palindrome Partitioning Problem
#include 
#include 
#include 
 
// A utility function to get minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
 
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minPalPartion(char* str)
{
    // Get the length of the string
    int n = strlen(str);
 
    /* Create two arrays to build the solution in bottom-up manner
       C[i] = Minimum number of cuts needed for a palindrome partitioning
                 of substring str[0..i]
       P[i][j] = true if substring str[i..j] is palindrome, else false
       Note that C[i] is 0 if P[0][i] is true */
    int C[n];
    bool P[n][n];
 
    int i, j, k, L; // different looping variables
 
    // Every substring of length 1 is a palindrome
    for (i = 0; i < n; i++) {
        P[i][i] = true;
    }
 
    /* L is substring length. Build the solution in bottom up manner by
       considering all substrings of length starting from 2 to n. */
    for (L = 2; L <= n; L++) {
        // For substring of length L, set different possible starting indexes
        for (i = 0; i < n - L + 1; i++) {
            j = i + L - 1; // Set ending index
 
            // If L is 2, then we just need to compare two characters. Else
            // need to check two corner characters and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1];
        }
    }
 
    for (i = 0; i < n; i++) {
        if (P[0][i] == true)
            C[i] = 0;
        else {
            C[i] = INT_MAX;
            for (j = 0; j < i; j++) {
                if (P[j + 1][i] == true && 1 + C[j] < C[i])
                    C[i] = 1 + C[j];
            }
        }
    }
 
    // Return the min cut value for complete string. i.e., str[0..n-1]
    return C[n - 1];
}
 
// Driver program to test above function
int main()
{
    char str[] = "ababbbabbababa";
    printf("Min cuts needed for Palindrome Partitioning is %d",
           minPalPartion(str));
    return 0;
}

Java

// Java Code for Palindrome Partitioning
// Problem
public class GFG {
    // Returns the minimum number of cuts needed
    // to partition a string such that every part
    // is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.length();
 
        /* Create two arrays to build the solution
        in bottom up manner
           C[i] = Minimum number of cuts needed for
           palindrome partitioning of substring
           str[0..i]
           P[i][j] = true if substring str[i..j] is
           palindrome, else false
           Note that C[i] is 0 if P[0][i] is true */
        int[] C = new int[n];
        boolean[][] P = new boolean[n][n];
 
        int i, j, k, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i][i] = true;
        }
 
        /* L is substring length. Build the solution
        in bottom up manner by considering all substrings
        of length starting from 2 to n. */
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i][j] = (str.charAt(i) == str.charAt(j));
                else
                    P[i][j] = (str.charAt(i) == str.charAt(j)) && P[i + 1][j - 1];
            }
        }
 
        for (i = 0; i < n; i++) {
            if (P[0][i] == true)
                C[i] = 0;
            else {
                C[i] = Integer.MAX_VALUE;
                for (j = 0; j < i; j++) {
                    if (P[j + 1][i] == true && 1 + C[j] < C[i])
                        C[i] = 1 + C[j];
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[n - 1];
    }
 
    // Driver program to test above function
    public static void main(String args[])
    {
        String str = "ababbbabbababa";
        System.out.println("Min cuts needed for "
                           + "Palindrome Partitioning"
                           + " is " + minPalPartion(str));
    }
}
// This code is contributed by Sumit Ghosh

蟒蛇3

# Dynamic Programming Solution for
# Palindrome Partitioning Problem
import sys
 
# Returns the minimum number of cuts
# needed to partition a string such
# that every part is a palindrome
def minPalPartion(str1):
     
    # Get the length of the string
    n = len(str1);
     
    # Create two arrays to build the solution
    # in bottom up manner
    # C[i] = Minimum number of cuts needed
    # for palindrome partitioning of
    # substring str[0..i]
    # P[i][j] = true if substring str[i..j]
    # is palindrome, else false
    # Note that C[i] is 0 if P[0][i] is true
    C = [0]*(n + 1);
    P = [[False for x in range(n + 1)] for y in range(n + 1)];
     
    # Every substring of length 1 is
    # a palindrome
    for i in range(n):
        P[i][i] = True;
     
    # L is substring length. Build the solution
    # in bottom up manner by considering all
    # substrings of length starting from 2 to n.
    for L in range(2, n + 1):
         
        # For substring of length L, set
        # different possible starting indexes
        for i in range(n - L + 1):
            j = i + L - 1;
             
            # Set ending index
            # If L is 2, then we just need to
            # compare two characters. Else need
            # to check two corner characters and
            # value of P[i + 1][j-1]
            if (L == 2):
                P[i][j] = (str1[i] == str1[j]);
            else:
                P[i][j] = ((str1[i] == str1[j]) and P[i + 1][j - 1]);
    for i in range(n):
        if (P[0][i] == True):
            C[i] = 0;
        else:
            C[i] = sys.maxsize;
            for j in range(i):
                if(P[j + 1][i] == True and 1 + C[j] < C[i]):
                    C[i] = 1 + C[j];
     
    # Return the min cut value for complete
    # string. i.e., str[0..n-1]
    return C[n - 1];
 
# Driver Code
str1 = "ababbbabbababa";
print("Min cuts needed for Palindrome Partitioning is", minPalPartion(str1));
 
# This code is contributed by mits

C#

// C# Code for Palindrome Partitioning
// Problem
using System;
 
class GFG {
 
    // Returns the minimum number of cuts needed
    // to partition a string such that every part
    // is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.Length;
 
        /* Create two arrays to build the solution
        in bottom up manner
        C[i] = Minimum number of cuts needed for
        palindrome partitioning of substring
        str[0..i]
        P[i][j] = true if substring str[i..j] is
        palindrome, else false
        Note that C[i] is 0 if P[0][i] is true */
        int[] C = new int[n];
        bool[, ] P = new bool[n, n];
 
        int i, j, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i, i] = true;
        }
 
        /* L is substring length. Build the solution
        in bottom up manner by considering all substrings
        of length starting from 2 to n. */
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i, j] = (str[i] == str[j]);
                else
                    P[i, j] = (str[i] == str[j]) && P[i + 1, j - 1];
            }
        }
 
        for (i = 0; i < n; i++) {
            if (P[0, i] == true)
                C[i] = 0;
            else {
                C[i] = int.MaxValue;
                for (j = 0; j < i; j++) {
                    if (P[j + 1, i] == true && 1 + C[j] < C[i])
                        C[i] = 1 + C[j];
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[n - 1];
    }
 
    // Driver program
    public static void Main()
    {
        String str = "ababbbabbababa";
        Console.Write("Min cuts needed for "
                      + "Palindrome Partitioning"
                      + " is " + minPalPartion(str));
    }
}
 
// This code is contributed by Sam007

PHP


输出:

Min cuts needed for Palindrome Partitioning is 3 

时间复杂度: O(n 2 )

使用 Memorization 来解决这个问题。
基本思想是缓存递归函数中计算出的间歇性结果。我们可以将这些结果放入一个 hashmap/unordered_map。
为了计算 Hashmap 的键,我们将使用字符串的开始和结束索引作为键,即 [“start_index”.append(“end_index”)] 将是 Hashmap 的键。

以下是上述方法的实现:

C++

// Using memoizatoin to solve the partition problem.
#include 
using namespace std;
// Function to check if input string is pallindrome or not
bool ispallindrome(string input, int start, int end)
{
    // Using two pointer technique to check pallindrome
    while (start < end) {
        if (input[start] != input[end])
            return false;
        start++;
        end--;
    }
    return true;
}
 
// Function to find keys for the Hashmap
string convert(int a, int b)
{
    return to_string(a) + "" + to_string(b);
}
 
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minpalparti_memo(string input, int i, int j, unordered_map& memo)
{
    if (i > j)
        return 0;
    // Key for the Input String
    string ij = convert(i, j);
 
    // If the no of partitions for string "ij" is already calculated
    // then return the calculated value using the Hashmap
    if (memo.find(ij) != memo.end()) {
        return memo[ij];
    }
    // Every String of length 1 is a pallindrome
    if (i == j) {
        memo[ij] = 0;
        return 0;
    }
    if (ispallindrome(input, i, j)) {
        memo[ij] = 0;
        return 0;
    }
    int minimum = INT_MAX;
    // Make a cut at every possible location starting from i to j
    for (int k = i; k < j; k++) {
        int left_min = INT_MAX;
        int right_min = INT_MAX;
        string left = convert(i, k);
        string right = convert(k + 1, j);
 
        // If left cut is found already
        if (memo.find(left) != memo.end()) {
            left_min = memo[left];
        }
        // If right cut is found already
        if (memo.find(right) != memo.end()) {
            right_min = memo[right];
        }
 
        // Recursively calculating for left and right strings
        if (left_min == INT_MAX)
            left_min = minpalparti_memo(input, i, k, memo);
        if (right_min == INT_MAX)
            right_min = minpalparti_memo(input, k + 1, j, memo);
 
        // Taking minimum of all k possible cuts
        minimum = min(minimum, left_min + 1 + right_min);
    }
 
    memo[ij] = minimum;
    // Return the min cut value for complete string.
    return memo[ij];
}
int main()
{
    string input = "ababbbabbababa";
    unordered_map memo;
    cout << minpalparti_memo(input, 0, input.length() - 1, memo) << endl;
    return 0;
}

蟒蛇3

# Using memoizatoin to solve the partition problem.
 
# Function to check if input string is pallindrome or not
def ispallindrome(input, start, end):
 
    # Using two pointer technique to check pallindrome
    while (start < end):
        if (input[start] != input[end]):
            return False;
        start += 1
        end -= 1
    return True;
 
# Function to find keys for the Hashmap
def convert(a, b):
    return str(a) + str(b);
 
# Returns the minimum number of cuts needed to partition a string
# such that every part is a palindrome
def minpalparti_memo(input, i, j, memo):
 
    if (i > j):
        return 0;
       
    # Key for the Input String
    ij = convert(i, j);
 
    # If the no of partitions for string "ij" is already calculated
    # then return the calculated value using the Hashmap
    if (ij in memo):
        return memo[ij];
     
    # Every String of length 1 is a pallindrome
    if (i == j):
        memo[ij] = 0;
        return 0;
    if (ispallindrome(input, i, j)):
        memo[ij] = 0;
        return 0;  
    minimum = 1000000000
     
    # Make a cut at every possible location starting from i to j
    for k in range(i, j):
        left_min = 1000000000
        right_min = 1000000000
        left = convert(i, k);
        right = convert(k + 1, j);
 
        # If left cut is found already
        if (left in memo):
            left_min = memo[left];
         
        # If right cut is found already
        if (right in memo):
            right_min = memo[right];
         
        # Recursively calculating for left and right strings
        if (left_min == 1000000000):
            left_min = minpalparti_memo(input, i, k, memo);
        if (right_min == 1000000000):
            right_min = minpalparti_memo(input, k + 1, j, memo);
 
        # Taking minimum of all k possible cuts
        minimum = min(minimum, left_min + 1 + right_min);
    memo[ij] = minimum;
     
    # Return the min cut value for complete string.
    return memo[ij];
 
  # Driver code
if __name__=='__main__':
 
    input = "ababbbabbababa";
    memo = dict()
    print(minpalparti_memo(input, 0, len(input) - 1, memo))
     
# This code is contributed by Pratham76.

时间复杂度: O(n 2 )

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