给定字符串str ,任务是找到由给定字符串str的前缀和后缀连接形成的最长回文子串。
例子:
Input: str = “rombobinnimor”
Output: rominnimor
Explanation:
The concatenation of string “rombob”(prefix) and “mor”(suffix) is “rombobmor” which is a palindromic string.
The concatenation of string “rom”(prefix) and “innimor”(suffix) is “rominnimor” which is a palindromic string.
But the length of “rominnimor” is greater than “rombobmor”.
Therefore, “rominnimor” is the required string.
Input: str = “geekinakeeg”
Output: geekakeeg
Explanation:
The concatenation of string “geek”(prefix) and “akeeg”(suffix) is “geekakeeg” which is a palindromic string.
The concatenation of string “geeki”(prefix) and “keeg”(suffix) is “geekigeek” which is a palindromic string.
But the length of “geekakeeg” is equals to “geekikeeg”.
Therefore, any of the above string is the required string.
方法:思想是使用 KMP 算法在 O(N) 时间内找到给定字符串str 后缀的回文最长的适当前缀。
- 找到最长的前缀(比如s[0, l] ),它也是字符串str 的后缀(比如s[nl, n-1] )的回文。前缀和后缀不重叠。
- 从剩余的子串( s[l+1, nl-1] )中,找到最长的回文子串(比如ans ),它是剩余字符串的后缀或前缀。
- s[0, l] 、 ans和s[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 greater 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
# greater 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 是给定字符串的长度。
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live