📜  最长回文子串的长度

📅  最后修改于: 2021-04-29 11:49:41             🧑  作者: Mango

给定长度为N的字符串S ,任务是从给定的字符串找到最长回文子字符串的长度。

例子:

天真的方法:解决问题的最简单方法是生成给定字符串的所有可能的子字符串,并打印最长的子字符串的长度,即回文。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to obtain the length of
// the longest palindromic substring
int longestPalSubstr(string str)
{
    // Length of given string
    int n = str.size();
 
    // Stores the maximum length
    int maxLength = 1, start = 0;
 
    // Iterate over the string
    for (int i = 0;
         i < str.length(); i++) {
 
        // Iterate over the string
        for (int j = i;
             j < str.length(); j++) {
            int flag = 1;
 
            // Check for palindrome
            for (int k = 0;
                 k < (j - i + 1) / 2; k++)
                if (str[i + k]
                    != str[j - k])
                    flag = 0;
 
            // If string [i, j - i + 1]
            // is palindromic
            if (flag
                && (j - i + 1) > maxLength) {
                start = i;
                maxLength = j - i + 1;
            }
        }
    }
 
    // Return length of LPS
    return maxLength;
}
 
// Driver Code
int main()
{
    // Given string
    string str = "forgeeksskeegfor";
 
    // Function Call
    cout << longestPalSubstr(str);
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
 
class GFG{
  
// Function to obtain the length of
// the longest palindromic substring
static int longestPalSubstr(String str)
{
     
    // Length of given string
    int n = str.length();
  
    // Stores the maximum length
    int maxLength = 1, start = 0;
  
    // Iterate over the string
    for(int i = 0; i < str.length(); i++)
    {
         
        // Iterate over the string
        for(int j = i; j < str.length(); j++)
        {
            int flag = 1;
  
            // Check for palindrome
            for(int k = 0;
                    k < (j - i + 1) / 2; k++)
                if (str.charAt(i + k) !=
                    str.charAt(j - k))
                    flag = 0;
  
            // If string [i, j - i + 1]
            // is palindromic
            if (flag != 0 &&
               (j - i + 1) > maxLength)
            {
                start = i;
                maxLength = j - i + 1;
            }
        }
    }
  
    // Return length of LPS
    return maxLength;
}
  
// Driver Code
public static void main (String[] args)
{
     
    // Given string
    String str = "forgeeksskeegfor";
  
    // Function call
    System.out.print(longestPalSubstr(str));
}
}
 
// This code is contributed by code_hunt


Python3
# Python3 program for the above approach
 
# Function to obtain the length of
# the longest palindromic substring
def longestPalSubstr(str):
     
    # Length of given string
    n = len(str)
  
    # Stores the maximum length
    maxLength = 1
    start = 0
  
    # Iterate over the string
    for i in range(len(str)):
  
        # Iterate over the string
        for j in range(i, len(str), 1):
            flag = 1
  
            # Check for palindrome
            for k in range((j - i + 1) // 2):
                if (str[i + k] != str[j - k]):
                    flag = 0
  
            # If string [i, j - i + 1]
            # is palindromic
            if (flag != 0 and
               (j - i + 1) > maxLength):
                start = i
                maxLength = j - i + 1
             
    # Return length of LPS
    return maxLength
 
# Driver Code
 
# Given string
str = "forgeeksskeegfor"
  
# Function call
print(longestPalSubstr(str))
 
# This code is contributed by code_hunt


C#
// C# program for the above approach 
using System;
 
class GFG{
  
// Function to obtain the length of
// the longest palindromic substring
static int longestPalSubstr(string str)
{
     
    // Length of given string
    int n = str.Length;
  
    // Stores the maximum length
    int maxLength = 1, start = 0;
  
    // Iterate over the string
    for(int i = 0; i < str.Length; i++)
    {
         
        // Iterate over the string
        for(int j = i; j < str.Length; j++)
        {
            int flag = 1;
  
            // Check for palindrome
            for(int k = 0;
                    k < (j - i + 1) / 2; k++)
                if (str[i + k] != str[j - k])
                    flag = 0;
  
            // If string [i, j - i + 1]
            // is palindromic
            if (flag != 0 &&
               (j - i + 1) > maxLength)
            {
                start = i;
                maxLength = j - i + 1;
            }
        }
    }
  
    // Return length of LPS
    return maxLength;
}
  
// Driver Code
public static void Main ()
{
     
    // Given string
    string str = "forgeeksskeegfor";
  
    // Function call
    Console.Write(longestPalSubstr(str));
}
}
 
// This code is contributed by code_hunt


C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to find the length of
// the longest palindromic substring
int longestPalSubstr(string str)
{
    // Length of string str
    int n = str.size();
 
    // Stores the dp states
    bool table[n][n];
 
    // Initialise table[][] as false
    memset(table, 0, sizeof(table));
 
    // All substrings of length 1
    // are palindromes
    int maxLength = 1;
 
    for (int i = 0; i < n; ++i)
        table[i][i] = true;
 
    // Check for sub-string of length 2
    int start = 0;
 
    for (int i = 0; i < n - 1; ++i) {
 
        // If adjacent character are same
        if (str[i] == str[i + 1]) {
 
            // Update table[i][i + 1]
            table[i][i + 1] = true;
            start = i;
            maxLength = 2;
        }
    }
 
    // Check for lengths greater than 2
    // k is length of substring
    for (int k = 3; k <= n; ++k) {
 
        // Fix the starting index
        for (int i = 0; i < n - k + 1; ++i) {
 
            // Ending index of substring
            // of length k
            int j = i + k - 1;
 
            // Check for palindromic
            // substring str[i, j]
            if (table[i + 1][j - 1]
                && str[i] == str[j]) {
 
                // Mark true
                table[i][j] = true;
 
                // Update the maximum length
                if (k > maxLength) {
                    start = i;
                    maxLength = k;
                }
            }
        }
    }
 
    // Return length of LPS
    return maxLength;
}
 
// Driver Code
int main()
{
    // Given string str
    string str = "forgeeksskeegfor";
 
    // Function Call
    cout << longestPalSubstr(str);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to find the length of
// the longest palindromic subString
static int longestPalSubstr(String str)
{
     
    // Length of String str
    int n = str.length();
 
    // Stores the dp states
    boolean [][]table = new boolean[n][n];
 
    // All subStrings of length 1
    // are palindromes
    int maxLength = 1;
 
    for(int i = 0; i < n; ++i)
        table[i][i] = true;
 
    // Check for sub-String of length 2
    int start = 0;
 
    for(int i = 0; i < n - 1; ++i)
    {
         
        // If adjacent character are same
        if (str.charAt(i) == str.charAt(i + 1))
        {
             
            // Update table[i][i + 1]
            table[i][i + 1] = true;
            start = i;
            maxLength = 2;
        }
    }
 
    // Check for lengths greater than 2
    // k is length of subString
    for(int k = 3; k <= n; ++k)
    {
         
        // Fix the starting index
        for(int i = 0; i < n - k + 1; ++i)
        {
             
            // Ending index of subString
            // of length k
            int j = i + k - 1;
 
            // Check for palindromic
            // subString str[i, j]
            if (table[i + 1][j - 1] &&
                str.charAt(i) == str.charAt(j))
            {
                 
                // Mark true
                table[i][j] = true;
 
                // Update the maximum length
                if (k > maxLength)
                {
                    start = i;
                    maxLength = k;
                }
            }
        }
    }
     
    // Return length of LPS
    return maxLength;
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Given String str
    String str = "forgeeksskeegfor";
 
    // Function Call
    System.out.print(longestPalSubstr(str));
}
}
 
// This code is contributed by Amit Katiyar


C#
// C# program for
// the above approach
using System;
class GFG{
 
// Function to find the length of
// the longest palindromic subString
static int longestPalSubstr(String str)
{
  // Length of String str
  int n = str.Length;
 
  // Stores the dp states
  bool [,]table = new bool[n, n];
 
  // All subStrings of length 1
  // are palindromes
  int maxLength = 1;
 
  for(int i = 0; i < n; ++i)
    table[i, i] = true;
 
  // Check for sub-String
  // of length 2
  int start = 0;
 
  for(int i = 0; i < n - 1; ++i)
  {
    // If adjacent character are same
    if (str[i] == str[i + 1])
    {
      // Update table[i,i + 1]
      table[i, i + 1] = true;
      start = i;
      maxLength = 2;
    }
  }
 
  // Check for lengths greater than 2
  // k is length of subString
  for(int k = 3; k <= n; ++k)
  {
    // Fix the starting index
    for(int i = 0; i < n - k + 1; ++i)
    {
      // Ending index of subString
      // of length k
      int j = i + k - 1;
 
      // Check for palindromic
      // subString str[i, j]
      if (table[i + 1, j - 1] &&
          str[i] == str[j])
      {
        // Mark true
        table[i, j] = true;
 
        // Update the maximum length
        if (k > maxLength)
        {
          start = i;
          maxLength = k;
        }
      }
    }
  }
 
  // Return length of LPS
  return maxLength;
}
 
// Driver Code
public static void Main(String[] args)
{
  // Given String str
  String str = "forgeeksskeegfor";
 
  // Function Call
  Console.Write(longestPalSubstr(str));
}
}
 
// This code is contributed by Rajput-Ji


Python3
# Python program for the above approach
 
 
# Function to find the length of
# the longest palindromic subString
def longestPalSubstr(str):
    # Length of String str
    n = len(str);
 
    # Stores the dp states
    table = [[False for i in range(n)] for j in range(n)];
 
    # All subStrings of length 1
    # are palindromes
    maxLength = 1;
 
    for i in range(n):
        table[i][i] = True;
 
    # Check for sub-String of length 2
    start = 0;
 
    for i in range(n - 1):
 
        # If adjacent character are same
        if (str[i] == str[i + 1]):
            # Update table[i][i + 1]
            table[i][i + 1] = True;
            start = i;
            maxLength = 2;
 
    # Check for lengths greater than 2
    # k is length of subString
    for k in range(3, n + 1):
 
        # Fix the starting index
        for i in range(n - k + 1):
 
            # Ending index of subString
            # of length k
            j = i + k - 1;
 
            # Check for palindromic
            # subString str[i, j]
            if (table[i + 1][j - 1] and str[i] == str[j]):
 
                # Mark True
                table[i][j] = True;
 
                # Update the maximum length
                if (k > maxLength):
                    start = i;
                    maxLength = k;
 
    # Return length of LPS
    return maxLength;
 
 
# Driver Code
if __name__ == '__main__':
    # Given String str
    str = "forgeeksskeegfor";
 
    # Function Call
    print(longestPalSubstr(str));
 
# This code is contributed by 29AjayKumar


Python3
# Python program for the above approach
 
# Function that placed '#' intermediately
# before and after each character
def UpdatedString(string):
 
    newString = ['#']
 
# Traverse the string
    for char in string:
        newString += [char, '#']
 
# Return the string
    return ''.join(newString)
 
# Function that finds the length of
# the longest palindromic substring
def Manacher(string):
 
    # Update the string
    string = UpdatedString(string)
 
    # Stores the longest proper prefix
    # which is also a suffix
    LPS = [0 for _ in range(len(string))]
    C = 0
    R = 0
 
    for i in range(len(string)):
        imir = 2 * C - i
 
        # Find the minimum length of
        # the palindrome
        if R > i:
            LPS[i] = min(R-i, LPS[imir])
        else:
 
            # Find the actual length of
            # the palindrome
            LPS[i] = 0
 
        # Exception Handling
        try:
            while string[i + 1 + LPS[i]] \
            == string[i - 1 - LPS[i]]:
                LPS[i] += 1
        except:
            pass
 
        # Update C and R
        if i + LPS[i] > R:
            C = i
            R = i + LPS[i]
 
    r, c = max(LPS), LPS.index(max(LPS))
 
    # Return the length r
    return r
 
 
# Driver code
 
# Given string str
str = "forgeeksskeegfor"
 
# Function Call
print(Manacher(str))


输出:
10









时间复杂度: O(N 3 ),其中N是给定字符串的长度。
辅助空间: O(N)

动态编程方法:可以通过存储重叠子问题的结果来优化上述方法。这个想法类似于这篇文章。步骤如下:

  1. 保持以自下而上的方式填充的布尔表[N] [N]
  2. 如果子字符串是回文,则table [i] [j]的值为true,否则为false。
  3. 要计算table [i] [j] ,请检查table [i + 1] [j – 1]的值,如果该值为true且str [i]str [j]相同,则更新table [i] [j]是的。
  4. 否则,将table [i] [j]的值更新为false。

下面是字符串“ geeks”的图示:

下面是上述方法的实现:

C++

// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to find the length of
// the longest palindromic substring
int longestPalSubstr(string str)
{
    // Length of string str
    int n = str.size();
 
    // Stores the dp states
    bool table[n][n];
 
    // Initialise table[][] as false
    memset(table, 0, sizeof(table));
 
    // All substrings of length 1
    // are palindromes
    int maxLength = 1;
 
    for (int i = 0; i < n; ++i)
        table[i][i] = true;
 
    // Check for sub-string of length 2
    int start = 0;
 
    for (int i = 0; i < n - 1; ++i) {
 
        // If adjacent character are same
        if (str[i] == str[i + 1]) {
 
            // Update table[i][i + 1]
            table[i][i + 1] = true;
            start = i;
            maxLength = 2;
        }
    }
 
    // Check for lengths greater than 2
    // k is length of substring
    for (int k = 3; k <= n; ++k) {
 
        // Fix the starting index
        for (int i = 0; i < n - k + 1; ++i) {
 
            // Ending index of substring
            // of length k
            int j = i + k - 1;
 
            // Check for palindromic
            // substring str[i, j]
            if (table[i + 1][j - 1]
                && str[i] == str[j]) {
 
                // Mark true
                table[i][j] = true;
 
                // Update the maximum length
                if (k > maxLength) {
                    start = i;
                    maxLength = k;
                }
            }
        }
    }
 
    // Return length of LPS
    return maxLength;
}
 
// Driver Code
int main()
{
    // Given string str
    string str = "forgeeksskeegfor";
 
    // Function Call
    cout << longestPalSubstr(str);
 
    return 0;
}

Java

// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to find the length of
// the longest palindromic subString
static int longestPalSubstr(String str)
{
     
    // Length of String str
    int n = str.length();
 
    // Stores the dp states
    boolean [][]table = new boolean[n][n];
 
    // All subStrings of length 1
    // are palindromes
    int maxLength = 1;
 
    for(int i = 0; i < n; ++i)
        table[i][i] = true;
 
    // Check for sub-String of length 2
    int start = 0;
 
    for(int i = 0; i < n - 1; ++i)
    {
         
        // If adjacent character are same
        if (str.charAt(i) == str.charAt(i + 1))
        {
             
            // Update table[i][i + 1]
            table[i][i + 1] = true;
            start = i;
            maxLength = 2;
        }
    }
 
    // Check for lengths greater than 2
    // k is length of subString
    for(int k = 3; k <= n; ++k)
    {
         
        // Fix the starting index
        for(int i = 0; i < n - k + 1; ++i)
        {
             
            // Ending index of subString
            // of length k
            int j = i + k - 1;
 
            // Check for palindromic
            // subString str[i, j]
            if (table[i + 1][j - 1] &&
                str.charAt(i) == str.charAt(j))
            {
                 
                // Mark true
                table[i][j] = true;
 
                // Update the maximum length
                if (k > maxLength)
                {
                    start = i;
                    maxLength = k;
                }
            }
        }
    }
     
    // Return length of LPS
    return maxLength;
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Given String str
    String str = "forgeeksskeegfor";
 
    // Function Call
    System.out.print(longestPalSubstr(str));
}
}
 
// This code is contributed by Amit Katiyar

C#

// C# program for
// the above approach
using System;
class GFG{
 
// Function to find the length of
// the longest palindromic subString
static int longestPalSubstr(String str)
{
  // Length of String str
  int n = str.Length;
 
  // Stores the dp states
  bool [,]table = new bool[n, n];
 
  // All subStrings of length 1
  // are palindromes
  int maxLength = 1;
 
  for(int i = 0; i < n; ++i)
    table[i, i] = true;
 
  // Check for sub-String
  // of length 2
  int start = 0;
 
  for(int i = 0; i < n - 1; ++i)
  {
    // If adjacent character are same
    if (str[i] == str[i + 1])
    {
      // Update table[i,i + 1]
      table[i, i + 1] = true;
      start = i;
      maxLength = 2;
    }
  }
 
  // Check for lengths greater than 2
  // k is length of subString
  for(int k = 3; k <= n; ++k)
  {
    // Fix the starting index
    for(int i = 0; i < n - k + 1; ++i)
    {
      // Ending index of subString
      // of length k
      int j = i + k - 1;
 
      // Check for palindromic
      // subString str[i, j]
      if (table[i + 1, j - 1] &&
          str[i] == str[j])
      {
        // Mark true
        table[i, j] = true;
 
        // Update the maximum length
        if (k > maxLength)
        {
          start = i;
          maxLength = k;
        }
      }
    }
  }
 
  // Return length of LPS
  return maxLength;
}
 
// Driver Code
public static void Main(String[] args)
{
  // Given String str
  String str = "forgeeksskeegfor";
 
  // Function Call
  Console.Write(longestPalSubstr(str));
}
}
 
// This code is contributed by Rajput-Ji

Python3

# Python program for the above approach
 
 
# Function to find the length of
# the longest palindromic subString
def longestPalSubstr(str):
    # Length of String str
    n = len(str);
 
    # Stores the dp states
    table = [[False for i in range(n)] for j in range(n)];
 
    # All subStrings of length 1
    # are palindromes
    maxLength = 1;
 
    for i in range(n):
        table[i][i] = True;
 
    # Check for sub-String of length 2
    start = 0;
 
    for i in range(n - 1):
 
        # If adjacent character are same
        if (str[i] == str[i + 1]):
            # Update table[i][i + 1]
            table[i][i + 1] = True;
            start = i;
            maxLength = 2;
 
    # Check for lengths greater than 2
    # k is length of subString
    for k in range(3, n + 1):
 
        # Fix the starting index
        for i in range(n - k + 1):
 
            # Ending index of subString
            # of length k
            j = i + k - 1;
 
            # Check for palindromic
            # subString str[i, j]
            if (table[i + 1][j - 1] and str[i] == str[j]):
 
                # Mark True
                table[i][j] = True;
 
                # Update the maximum length
                if (k > maxLength):
                    start = i;
                    maxLength = k;
 
    # Return length of LPS
    return maxLength;
 
 
# Driver Code
if __name__ == '__main__':
    # Given String str
    str = "forgeeksskeegfor";
 
    # Function Call
    print(longestPalSubstr(str));
 
# This code is contributed by 29AjayKumar
输出:
10









时间复杂度: O(N 2 ),其中N是给定字符串的长度。
辅助空间: O(N)

高效方法:为了优化上述方法,其思想是使用Manacher算法。通过使用该算法,对于每个字符c ,可以找到以c为中心的最长回文子字符串,其长度为奇数。但最长回文子串的长度也可以均匀,没有任何中心。因此,一些特殊字符的每个字符之间增加。

步骤如下:

  1. 如上所述,在给定的字符串S中添加特殊字符,并将其长度设为N。
  2. 0初始化数组d [] ,center和r ,其中d [i]存储回文的左侧部分的长度,其中S [i]是中心, r表示最右边的访问边界,center表示当前索引。字符,它是此最右边边界的中心。
  3. 在遍历字符串S时,对于每个索引i ,如果i小于r,则先前已计算出其答案,并且可以将d [i]设置为等于以i为中心的字符镜像的答案,可以将其计算为(2 *中心– i)
  4. 现在,检查r后面是否有某些字符,以使回文变得越来越长。
  5. 如果(i + d [i])大于r ,则更新r = (i + d [i])并以i为中心。
  6. 在找到以每个字符c为中心的最长回文之后,打印(2 * d [i] + 1)/ 2的最大值,其中0≤i 因为d [i]仅存储回文的左侧部分。

下面是上述方法的实现:

Python3

# Python program for the above approach
 
# Function that placed '#' intermediately
# before and after each character
def UpdatedString(string):
 
    newString = ['#']
 
# Traverse the string
    for char in string:
        newString += [char, '#']
 
# Return the string
    return ''.join(newString)
 
# Function that finds the length of
# the longest palindromic substring
def Manacher(string):
 
    # Update the string
    string = UpdatedString(string)
 
    # Stores the longest proper prefix
    # which is also a suffix
    LPS = [0 for _ in range(len(string))]
    C = 0
    R = 0
 
    for i in range(len(string)):
        imir = 2 * C - i
 
        # Find the minimum length of
        # the palindrome
        if R > i:
            LPS[i] = min(R-i, LPS[imir])
        else:
 
            # Find the actual length of
            # the palindrome
            LPS[i] = 0
 
        # Exception Handling
        try:
            while string[i + 1 + LPS[i]] \
            == string[i - 1 - LPS[i]]:
                LPS[i] += 1
        except:
            pass
 
        # Update C and R
        if i + LPS[i] > R:
            C = i
            R = i + LPS[i]
 
    r, c = max(LPS), LPS.index(max(LPS))
 
    # Return the length r
    return r
 
 
# Driver code
 
# Given string str
str = "forgeeksskeegfor"
 
# Function Call
print(Manacher(str))
输出:
10









时间复杂度: O(N),其中N是给定字符串的长度。
辅助空间: O(N)