📌  相关文章
📜  计算字符串中的所有回文子字符串|套装1

📅  最后修改于: 2021-04-23 08:04:25             🧑  作者: Mango

给定一个字符串,任务是计算一个给定的字符串中的所有回文子字符串。回文子字符串的长度大于或等于2。

例子:

Input : str = "abaab"
Output: 3
Explanation : 
All palindrome substring are :
 "aba" , "aa" , "baab" 

Input : str = "abbaeae"
Output: 4
Explanation : 
All palindrome substring are : 
"bb" , "abba" ,"aea","eae"

我们在下面讨论了类似的问题。
查找给定字符串的所有不同回文子字符串

可以递归定义以上问题。

Initial Values : i = 0, j = n-1;
Given string 'str'

CountPS(i, j)
   
   // If length of string is 2 then we 
   // check both character are same or not 
   If (j == i+1)
      return str[i] == str[j]
   //this condition shows that in recursion if i crosses j then it will be a invalid substring or
   //if i==j that means only one character is remaining and we require substring of length 2 
   //in both the conditions we need to return 0
   Else if(i == j ||  i > j) return 0;
   Else If str[i..j] is PALINDROME 
      // increment count by 1 and check for 
      // rest palindromic substring (i, j-1), (i+1, j)
      // remove common palindrome substring (i+1, j-1)
      return  countPS(i+1, j) + countPS(i, j-1) + 1 -
                                   countPS(i+1, j-1);

    Else // if NOT PALINDROME 
       // We check for rest palindromic substrings (i, j-1)
       // and (i+1, j)
       // remove common palindrome substring (i+1 , j-1)
       return  countPS(i+1, j) + countPS(i, j-1) - 
                             countPS(i+1 , j-1);

如果我们绘制上述递归解的递归树,则可以观察到重叠的子问题。由于该问题具有重叠的子问题,因此我们可以使用动态编程有效地解决它。以下是基于动态编程的解决方案。

C++
// C++ program to find palindromic substrings of a string
#include 
using namespace std;
 
// Returns total number of palindrome substring of
// length greater then equal to 2
int CountPS(char str[], int n)
{
    // create empty 2-D matrix that counts all palindrome
    // substring. dp[i][j] stores counts of palindromic
    // substrings in st[i..j]
    int dp[n][n];
    memset(dp, 0, sizeof(dp));
 
    // P[i][j] = true if substring str[i..j] is palindrome,
    // else false
    bool P[n][n];
    memset(P, false, sizeof(P));
 
    // palindrome of single length
    for (int i = 0; i < n; i++)
        P[i][i] = true;
 
    // palindrome of length 2
    for (int i = 0; i < n - 1; i++) {
        if (str[i] == str[i + 1]) {
            P[i][i + 1] = true;
            dp[i][i + 1] = 1;
        }
    }
 
    // Palindromes of length more than 2. This loop is
    // similar to Matrix Chain Multiplication. We start with
    // a gap of length 2 and fill the DP table in a way that
    // gap between starting and ending indexes increases one
    // by one by outer loop.
    for (int gap = 2; gap < n; gap++) {
        // Pick starting point for current gap
        for (int i = 0; i < n - gap; i++) {
            // Set ending point
            int j = gap + i;
 
            // If current string is palindrome
            if (str[i] == str[j] && P[i + 1][j - 1])
                P[i][j] = true;
 
            // Add current palindrome substring ( + 1)
            // and rest palindrome substring (dp[i][j-1] +
            // dp[i+1][j]) remove common palindrome
            // substrings (- dp[i+1][j-1])
            if (P[i][j] == true)
                dp[i][j] = dp[i][j - 1] + dp[i + 1][j] + 1
                           - dp[i + 1][j - 1];
            else
                dp[i][j] = dp[i][j - 1] + dp[i + 1][j]
                           - dp[i + 1][j - 1];
        }
    }
 
    // return total palindromic substrings
    return dp[0][n - 1];
}
 
// Driver code
int main()
{
    char str[] = "abaab";
    int n = strlen(str);
    cout << CountPS(str, n) << endl;
    return 0;
}


Java
// Java program to find palindromic substrings of a string
 
public class GFG {
    // Returns total number of palindrome substring of
    // length greater then equal to 2
    static int CountPS(char str[], int n)
    {
        // create empty 2-D matrix that counts all
        // palindrome substring. dp[i][j] stores counts of
        // palindromic substrings in st[i..j]
        int dp[][] = new int[n][n];
 
        // P[i][j] = true if substring str[i..j] is
        // palindrome, else false
        boolean P[][] = new boolean[n][n];
 
        // palindrome of single length
        for (int i = 0; i < n; i++)
            P[i][i] = true;
 
        // palindrome of length 2
        for (int i = 0; i < n - 1; i++) {
            if (str[i] == str[i + 1]) {
                P[i][i + 1] = true;
                dp[i][i + 1] = 1;
            }
        }
 
        // Palindromes of length more than 2. This loop is
        // similar to Matrix Chain Multiplication. We start
        // with a gap of length 2 and fill the DP table in a
        // way that gap between starting and ending indexes
        // increases one by one by outer loop.
        for (int gap = 2; gap < n; gap++) {
            // Pick starting point for current gap
            for (int i = 0; i < n - gap; i++) {
                // Set ending point
                int j = gap + i;
 
                // If current string is palindrome
                if (str[i] == str[j] && P[i + 1][j - 1])
                    P[i][j] = true;
 
                // Add current palindrome substring ( + 1)
                // and rest palindrome substring (dp[i][j-1]
                // + dp[i+1][j]) remove common palindrome
                // substrings (- dp[i+1][j-1])
                if (P[i][j] == true)
                    dp[i][j] = dp[i][j - 1] + dp[i + 1][j]
                               + 1 - dp[i + 1][j - 1];
                else
                    dp[i][j] = dp[i][j - 1] + dp[i + 1][j]
                               - dp[i + 1][j - 1];
            }
        }
 
        // return total palindromic substrings
        return dp[0][n - 1];
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String str = "abaab";
        System.out.println(
            CountPS(str.toCharArray(), str.length()));
    }
}


Python3
# Python3 program to find palindromic
# substrings of a string
 
# Returns total number of palindrome
# substring of length greater then
# equal to 2
 
 
def CountPS(str, n):
 
    # creat empty 2-D matrix that counts
    # all palindrome substring. dp[i][j]
    # stores counts of palindromic
    # substrings in st[i..j]
    dp = [[0 for x in range(n)]
          for y in range(n)]
 
    # P[i][j] = true if substring str[i..j]
    # is palindrome, else false
    P = [[False for x in range(n)]
         for y in range(n)]
 
    # palindrome of single length
    for i in range(n):
        P[i][i] = True
 
    # palindrome of length 2
    for i in range(n - 1):
        if (str[i] == str[i + 1]):
            P[i][i + 1] = True
            dp[i][i + 1] = 1
 
    # Palindromes of length more than 2. This
    # loop is similar to Matrix Chain Multiplication.
    # We start with a gap of length 2 and fill DP
    # table in a way that the gap between starting and
    # ending indexes increase one by one by
    # outer loop.
    for gap in range(2, n):
 
        # Pick a starting point for the current gap
        for i in range(n - gap):
 
            # Set ending point
            j = gap + i
 
            # If current string is palindrome
            if (str[i] == str[j] and P[i + 1][j - 1]):
                P[i][j] = True
 
            # Add current palindrome substring ( + 1)
            # and rest palindrome substring (dp[i][j-1] +
            # dp[i+1][j]) remove common palindrome
            # substrings (- dp[i+1][j-1])
            if (P[i][j] == True):
                dp[i][j] = (dp[i][j - 1] +
                            dp[i + 1][j] + 1 - dp[i + 1][j - 1])
            else:
                dp[i][j] = (dp[i][j - 1] +
                            dp[i + 1][j] - dp[i + 1][j - 1])
 
    # return total palindromic substrings
    return dp[0][n - 1]
 
 
# Driver Code
if __name__ == "__main__":
 
    str = "abaab"
    n = len(str)
    print(CountPS(str, n))
 
# This code is contributed by ita_c


C#
// C# program to find palindromic
// substrings of a string
using System;
 
class GFG {
    // Returns total number of
    // palindrome substring of
    // length greater then equal to 2
    public static int CountPS(char[] str, int n)
    {
        // create empty 2-D matrix that counts
        // all palindrome substring. dp[i][j]
        // stores counts of palindromic
        // substrings in st[i..j]
 
        int[][] dp
            = RectangularArrays.ReturnRectangularIntArray(
                n, n);
 
        // P[i][j] = true if substring str[i..j]
        // is palindrome, else false
 
        bool[][] P
            = RectangularArrays.ReturnRectangularBoolArray(
                n, n);
 
        // palindrome of single length
        for (int i = 0; i < n; i++) {
            P[i][i] = true;
        }
 
        // palindrome of length 2
        for (int i = 0; i < n - 1; i++) {
            if (str[i] == str[i + 1]) {
                P[i][i + 1] = true;
                dp[i][i + 1] = 1;
            }
        }
 
        // Palindromes of length more then 2.
        // This loop is similar to Matrix Chain
        // Multiplication. We start with a gap
        // of length 2 and fill DP table in a
        // way that gap between starting and
        // ending indexes increases one by one
        // by outer loop.
        for (int gap = 2; gap < n; gap++) {
            // Pick starting point for current gap
            for (int i = 0; i < n - gap; i++) {
                // Set ending point
                int j = gap + i;
 
                // If current string is palindrome
                if (str[i] == str[j] && P[i + 1][j - 1]) {
                    P[i][j] = true;
                }
 
                // Add current palindrome substring
                // ( + 1) and rest palindrome substring
                // (dp[i][j-1] + dp[i+1][j]) remove common
                // palindrome substrings (- dp[i+1][j-1])
                if (P[i][j] == true) {
                    dp[i][j] = dp[i][j - 1] + dp[i + 1][j]
                               + 1 - dp[i + 1][j - 1];
                }
                else {
                    dp[i][j] = dp[i][j - 1] + dp[i + 1][j]
                               - dp[i + 1][j - 1];
                }
            }
        }
 
        // return total palindromic substrings
        return dp[0][n - 1];
    }
 
    public static class RectangularArrays {
        public static int[][] ReturnRectangularIntArray(
            int size1, int size2)
        {
            int[][] newArray = new int[size1][];
            for (int array1 = 0; array1 < size1; array1++) {
                newArray[array1] = new int[size2];
            }
 
            return newArray;
        }
 
        public static bool[][] ReturnRectangularBoolArray(
            int size1, int size2)
        {
            bool[][] newArray = new bool[size1][];
            for (int array1 = 0; array1 < size1; array1++) {
                newArray[array1] = new bool[size2];
            }
 
            return newArray;
        }
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
        string str = "abaab";
        Console.WriteLine(
            CountPS(str.ToCharArray(), str.Length));
    }
}
 
// This code is contributed by Shrikant13


PHP


Javascript


C++
#include 
using namespace std;
 
int dp[1001][1001]; // 2D matrix
bool isPal(string s, int i, int j)
{
    // Base condition
    if (i > j)
        return 1;
 
    // check if the recursive tree
    // for given i, j
    // has already been executed
    if (dp[i][j] != -1)
        return dp[i][j];
 
    // If first and last characters of
    // substring are unequal
    if (s[i] != s[j])
        return dp[i][j] = 0;
 
    // memoization
    return dp[i][j] = isPal(s, i + 1, j - 1);
}
 
int countSubstrings(string s)
{
    memset(dp, -1, sizeof(dp));
    int n = s.length();
    int count = 0;
 
    // 2 for loops are required to check for
    // all the palindromes in the string.
    for (int i = 0; i < n; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            // Increment count for every palindrome
            if (isPal(s, i, j))
                count++;
        }
    }
    // return total palindromic substrings
    return count;
}
 
// Driver code
int main()
{
 
    string s = "abbaeae";
 
    cout << countSubstrings(s);
 
    //"bb" , "abba" ,"aea", "eae" are
    // the 4 palindromic substrings.
 
    // This code is contributed by Bhavneet Singh
 
    return 0;
}


Java
import java.util.*;
public class Main
{
    static int dp[][] = new int[1001][1001]; // 2D matrix
     
    public static int isPal(String s, int i, int j)
    {
        // Base condition
        if (i > j)
            return 1;
      
        // check if the recursive tree
        // for given i, j
        // has already been executed
        if (dp[i][j] != -1)
            return dp[i][j];
      
        // If first and last characters of
        // substring are unequal
        if (s.charAt(i) != s.charAt(j))
            return dp[i][j] = 0;
      
        // memoization
        return dp[i][j] = isPal(s, i + 1, j - 1);
    }
      
    public static int countSubstrings(String s)
    {
        for (int[] row: dp)
        {
            Arrays.fill(row, -1);
        }
        int n = s.length();
        int count = 0;
      
        // 2 for loops are required to check for
        // all the palindromes in the string.
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                // Increment count for every palindrome
                if (isPal(s, i, j) != 0)
                    count++;
            }
        }
       
        // return total palindromic substrings
        return count;
    }
 
    public static void main(String[] args) {
        String s = "abbaeae";
  
        System.out.println(countSubstrings(s));
    }
}
 
// This code is contributed by divyeshrabadiya07


Python3
# 2D matrix
dp = [[-1 for i in range(1001)]
          for j in range(1001)]
 
def isPal(s, i, j):
     
    # Base condition
    if (i > j):
        return 1
 
    # Check if the recursive tree
    # for given i, j
    # has already been executed
    if (dp[i][j] != -1):
        return dp[i][j]
 
    # If first and last characters of
    # substring are unequal
    if (s[i] != s[j]):
        dp[i][j] = 0
        return dp[i][j]
         
    # Memoization
    dp[i][j] = isPal(s, i + 1, j - 1)
     
    return dp[i][j]
 
def countSubstrings(s):
     
    n = len(s)
 
    count = 0
 
    # 2 for loops are required to check for
    # all the palindromes in the string.
    for i in range(n):
        for j in range(i + 1, n):
             
            # Increment count for every palindrome
            if (isPal(s, i, j)):
                count += 1
 
    # Return total palindromic substrings
    return count
 
# Driver code
s = "abbaeae"
 
print(countSubstrings(s))
 
# This code is contributed by rag2127


C#
using System;
 
class GFG{
 
// 2D matrix
static int[,] dp = new int[1001, 1001];
 
static int isPal(string s, int i, int j)
{
     
    // Base condition
    if (i > j)
        return 1;
   
    // Check if the recursive tree
    // for given i, j
    // has already been executed
    if (dp[i, j] != -1)
        return dp[i, j];
   
    // If first and last characters of
    // substring are unequal
    if (s[i] != s[j])
        return dp[i, j] = 0;
   
    // Memoization
    return dp[i, j] = isPal(s, i + 1, j - 1);
}
   
static int countSubstrings(string s)
{
    for(int i = 0; i < 1001; i++)
    {
        for(int j = 0; j < 1001; j++)
        {
            dp[i, j] = -1;
        }
    }
     
    int n = s.Length;
    int count = 0;
   
    // 2 for loops are required to check for
    // all the palindromes in the string.
    for(int i = 0; i < n; i++)
    {
        for(int j = i + 1; j < n; j++)
        {
             
            // Increment count for every palindrome
            if (isPal(s, i, j) != 0)
                count++;
        }
    }
     
    // Return total palindromic substrings
    return count;
}
 
// Driver Code   
static void Main()
{
    string s = "abbaeae";
     
    Console.WriteLine(countSubstrings(s));
}
}
 
// This code is contributed by divyesh072019


输出:

3

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

方法2:

此方法使用自上而下的DP,即递归的记忆版本。

Recursive soln:
1. Here base condition comes out to be i>j if we hit this condition, return 1.
2. We check for each and every i and j, if the characters are equal, 
   if that is not the case, return 0.
3. Call the is_palindrome function again with incremented i  and decremented j.
4. Check this for all values of i and j by applying 2 for loops.

C++

#include 
using namespace std;
 
int dp[1001][1001]; // 2D matrix
bool isPal(string s, int i, int j)
{
    // Base condition
    if (i > j)
        return 1;
 
    // check if the recursive tree
    // for given i, j
    // has already been executed
    if (dp[i][j] != -1)
        return dp[i][j];
 
    // If first and last characters of
    // substring are unequal
    if (s[i] != s[j])
        return dp[i][j] = 0;
 
    // memoization
    return dp[i][j] = isPal(s, i + 1, j - 1);
}
 
int countSubstrings(string s)
{
    memset(dp, -1, sizeof(dp));
    int n = s.length();
    int count = 0;
 
    // 2 for loops are required to check for
    // all the palindromes in the string.
    for (int i = 0; i < n; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            // Increment count for every palindrome
            if (isPal(s, i, j))
                count++;
        }
    }
    // return total palindromic substrings
    return count;
}
 
// Driver code
int main()
{
 
    string s = "abbaeae";
 
    cout << countSubstrings(s);
 
    //"bb" , "abba" ,"aea", "eae" are
    // the 4 palindromic substrings.
 
    // This code is contributed by Bhavneet Singh
 
    return 0;
}

Java

import java.util.*;
public class Main
{
    static int dp[][] = new int[1001][1001]; // 2D matrix
     
    public static int isPal(String s, int i, int j)
    {
        // Base condition
        if (i > j)
            return 1;
      
        // check if the recursive tree
        // for given i, j
        // has already been executed
        if (dp[i][j] != -1)
            return dp[i][j];
      
        // If first and last characters of
        // substring are unequal
        if (s.charAt(i) != s.charAt(j))
            return dp[i][j] = 0;
      
        // memoization
        return dp[i][j] = isPal(s, i + 1, j - 1);
    }
      
    public static int countSubstrings(String s)
    {
        for (int[] row: dp)
        {
            Arrays.fill(row, -1);
        }
        int n = s.length();
        int count = 0;
      
        // 2 for loops are required to check for
        // all the palindromes in the string.
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                // Increment count for every palindrome
                if (isPal(s, i, j) != 0)
                    count++;
            }
        }
       
        // return total palindromic substrings
        return count;
    }
 
    public static void main(String[] args) {
        String s = "abbaeae";
  
        System.out.println(countSubstrings(s));
    }
}
 
// This code is contributed by divyeshrabadiya07

Python3

# 2D matrix
dp = [[-1 for i in range(1001)]
          for j in range(1001)]
 
def isPal(s, i, j):
     
    # Base condition
    if (i > j):
        return 1
 
    # Check if the recursive tree
    # for given i, j
    # has already been executed
    if (dp[i][j] != -1):
        return dp[i][j]
 
    # If first and last characters of
    # substring are unequal
    if (s[i] != s[j]):
        dp[i][j] = 0
        return dp[i][j]
         
    # Memoization
    dp[i][j] = isPal(s, i + 1, j - 1)
     
    return dp[i][j]
 
def countSubstrings(s):
     
    n = len(s)
 
    count = 0
 
    # 2 for loops are required to check for
    # all the palindromes in the string.
    for i in range(n):
        for j in range(i + 1, n):
             
            # Increment count for every palindrome
            if (isPal(s, i, j)):
                count += 1
 
    # Return total palindromic substrings
    return count
 
# Driver code
s = "abbaeae"
 
print(countSubstrings(s))
 
# This code is contributed by rag2127

C#

using System;
 
class GFG{
 
// 2D matrix
static int[,] dp = new int[1001, 1001];
 
static int isPal(string s, int i, int j)
{
     
    // Base condition
    if (i > j)
        return 1;
   
    // Check if the recursive tree
    // for given i, j
    // has already been executed
    if (dp[i, j] != -1)
        return dp[i, j];
   
    // If first and last characters of
    // substring are unequal
    if (s[i] != s[j])
        return dp[i, j] = 0;
   
    // Memoization
    return dp[i, j] = isPal(s, i + 1, j - 1);
}
   
static int countSubstrings(string s)
{
    for(int i = 0; i < 1001; i++)
    {
        for(int j = 0; j < 1001; j++)
        {
            dp[i, j] = -1;
        }
    }
     
    int n = s.Length;
    int count = 0;
   
    // 2 for loops are required to check for
    // all the palindromes in the string.
    for(int i = 0; i < n; i++)
    {
        for(int j = i + 1; j < n; j++)
        {
             
            // Increment count for every palindrome
            if (isPal(s, i, j) != 0)
                count++;
        }
    }
     
    // Return total palindromic substrings
    return count;
}
 
// Driver Code   
static void Main()
{
    string s = "abbaeae";
     
    Console.WriteLine(countSubstrings(s));
}
}
 
// This code is contributed by divyesh072019
输出
4

计算字符串中的所有回文子字符串|套装2