📌  相关文章
📜  由前缀的级联和后缀字符串形成的最长回文字符串

📅  最后修改于: 2021-04-26 08:15:20             🧑  作者: Mango

给定字符串str ,任务是找到由给定字符串str的前缀和后缀串联而成的最长回文子字符串。
例子:

方法:想法是使用KMP算法找到最长的正确前缀,它是给定字符串str在O(N)时间后缀的回文。

  1. 找到最长的前缀(例如s [0,l] ),它也是字符串str后缀(例如s [nl,n-1] )的回文。前缀和后缀不重叠。
  2. 在其余子串( s [l + 1,nl-1] )中,找到最长回文子串(例如ans ),该子串可以是剩余字符串的后缀或前缀。
  3. s [0,l]anss [nl,nl-1]的串联是最长回文子串。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
#include 
using namespace std;
 
// Function used to calculate the longest prefix
// which is also a suffix
int kmp(string s)
{
    vector lps(s.size(), 0);
 
    // Traverse the string
    for (int i = 1; i < s.size(); i++) {
 
        int previous_index = lps[i - 1];
 
        while (previous_index > 0
               && s[i] != s[previous_index]) {
 
            previous_index = lps[previous_index - 1];
        }
 
        // Update the lps size
        lps[i] = previous_index
                 + (s[i] == s[previous_index] ? 1 : 0);
    }
 
    // Returns size of lps
    return lps[lps.size() - 1];
}
 
// Function to calculate the length of longest
// palindromic substring whcih is either a
// suffix or prefix
int remainingStringLongestPallindrome(string s)
{
    // Append a character to separate the string
    // and reverse of the string
    string t = s + "?";
 
    // Reverse the string
    reverse(s.begin(), s.end());
 
    // Append the reversed string
    t += s;
 
    return kmp(t);
}
 
// Function to find the Longest palindromic
// string formed from concatenation of prefix
// and suffix of a given string
string longestPrefixSuffixPallindrome(string s)
{
    int length = 0;
    int n = s.size();
 
    // Calculating the length for which prefix
    // is reverse of suffix
    for (int i = 0, j = n - 1; i < j; i++, j--) {
        if (s[i] != s[j]) {
            break;
        }
        length++;
    }
 
    // Append prefix to the answer
    string ans = s.substr(0, length);
  
 
    // Store the remaining string
    string remaining = s.substr(length,
                                (n - (2 * length)));
   
 
    // If the remaining string is not empty
    // that means that there can be a palindrome
    // substring which can be added between the
    // suffix & prefix
    if (remaining.size()) {
 
        // Calculate the length of longest prefix
        // palindromic substring
        int longest_prefix
            = remainingStringLongestPallindrome(remaining);
 
        // Reverse the given string to find the
        // longest palindromic suffix
        reverse(remaining.begin(), remaining.end());
       
        // Calculate the length of longest prefix
        // palindromic substring
        int longest_suffix
            = remainingStringLongestPallindrome(remaining);
 
        // If the prefix palindrome is greater
        // than the suffix palindrome
        if (longest_prefix > longest_suffix) {
 
            reverse(remaining.begin(), remaining.end());
 
            // Append the prefix to the answer
            ans += remaining.substr(0, longest_prefix);
        }
 
        // If the suffix palindrome is greter than
        // the prefix palindrome
 
        else {
 
            // Append the suffix to the answer
            ans += remaining.substr(0, longest_suffix);
        }
    }
 
    // Finally append the suffix to the answer
    ans += s.substr(n - length, length);
 
    // Return the answer string
    return ans;
}
 
// Driver Code
int main()
{
    string str = "rombobinnimor";
 
    cout << longestPrefixSuffixPallindrome(str)
         << endl;
}


Python3
# Python3 implementation of
# the above approach
 
# Function used to calculate
# the longest prefix
# which is also a suffix
def kmp(s):
 
    lps = [0] * (len(s))
 
    # Traverse the string
    for i in range (1 , len(s)):
 
        previous_index = lps[i - 1]
 
        while (previous_index > 0 and
               s[i] != s[previous_index]):
 
            previous_index = lps[previous_index - 1]
        
        # Update the lps size
        lps[i] = previous_index
        if (s[i] == s[previous_index]):
            lps[i] += 1
 
    # Returns size of lps
    return lps[- 1]
 
# Function to calculate the length of
# longest palindromic substring which
# is either a suffix or prefix
def remainingStringLongestPallindrome(s):
 
    # Append a character to separate
    # the string and reverse of the string
    t = s + "?"
 
    # Reverse the string
    s = s[: : -1]
 
    # Append the reversed string
    t += s
 
    return kmp(t)
 
# Function to find the Longest
# palindromic string formed from
# concatenation of prefix
# and suffix of a given string
def longestPrefixSuffixPallindrome(s):
 
    length = 0
    n = len(s)
 
    # Calculating the length
    # for which prefix
    # is reverse of suffix
    i = 0
    j = n - 1
    while i < j:
        if (s[i] != s[j]):
            break
        i += 1
        j -= 1
         
        length += 1
 
    # Append prefix to the answer
    ans = s[0 : length]
 
    # Store the remaining string
    remaining = s[length :  length + (n - (2 * length))]
 
    # If the remaining string is not empty
    # that means that there can be a palindrome
    # substring which can be added between the
    # suffix & prefix
    if (len(remaining)):
 
        # Calculate the length of longest prefix
        # palindromic substring
        longest_prefix = remainingStringLongestPallindrome(remaining);
 
        # Reverse the given string to find the
        # longest palindromic suffix
        remaining = remaining[: : -1]
 
        # Calculate the length of longest prefix
        # palindromic substring
        longest_suffix = remainingStringLongestPallindrome(remaining);
 
        # If the prefix palindrome is greater
        # than the suffix palindrome
        if (longest_prefix > longest_suffix):
 
            remaining = remaining[: : -1]
 
            # Append the prefix to the answer
            ans += remaining[0 : longest_prefix]
        
        # If the suffix palindrome is
        # greter than the prefix palindrome
        else:
 
            # Append the suffix to the answer
            ans += remaining[0 : longest_suffix]
        
    # Finally append the suffix to the answer
    ans += s[n - length : n]
 
    # Return the answer string
    return ans
 
# Driver Code
if __name__ == "__main__": 
    st = "rombobinnimor"
    print (longestPrefixSuffixPallindrome(st))
          
# This code is contributed by Chitranayal


输出:
rominnimor



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