面试题之最长回文字串

这个问题也是一个很有名的问题了,在pongba的群里面问起过,还有人引出了suffix tree来解决这样的问题,这个就是最长回文字的问题

How will you find the longest palindrome in a string? I.e. if the string is XMADAMYX, Your code should print MADAM

这个问题用后缀树解决可以在O(n)的时间里面完成,但是我想在真正面试的时候,估计很难从容淡定到可以写出一个后缀树(尤其是压缩的后缀树),有 关后缀树可以看看wikipedia上的原文(http://en.wikipedia.org/wiki/Suffix_tree)。所以本着更实用可 行的办法,还是要用动态规划来实现。

想法很简单,回文字符串的意思就是这个字符串正序和逆序是完全相同的,本着这样的特性,我们很自然联想到,如果把字符串倒序,然后求出原字符串和倒序串的最长公共子串 就 行了,注意这里的意思Longest Common SubString不是Longest Common SubSequence,因为显然我们需要的是一个连续的字符串。对于这样的问题,老套路了,求出动态规划的递推公式,然后写代码。我们这里假设原串是S1,倒序串味S2的话,我们可以得到递推式:

if (Si[i] == S2[j]) M[i,j] = M[i-1,j-1] + 1;

else                    M[i,j] = 0;

其实这样的递推式很直观,如果存在(Si[i] == S2[j])说明找到了相同的字符串,那对应位置的相同串的长度需要加一,我们的问题就是找到最大的长度,然后把对应的字串打印出来。

下面就是对应的代码:

#include <iostream> #include <algorithm> #include <vector> bool findLongestPalindrome (const std::string& source, std::string& result) { std::string reverse (source.begin(), source.end()); std::reverse(reverse.begin(),reverse.end()); std::vector< std::vector<int> > M ( source.size()+1, std::vector<int> (source.size()+1) ); int maxLength = 0; int maxIndexi = 0; for (unsigned int i=1;i<=source.size();i++) { for (unsigned int j=1;j<=reverse.size();j++) { if ( source[i-1] == reverse[j-1] ) { M[i][j] = M[i-1][j-1] + 1; if (M[i][j]>=maxLength) { maxLength = M[i][j]; maxIndexi = i; } } else M[i][j] = 0; } } if (maxLength != 0) { result = reverse.substr(reverse.size()-maxIndexi,maxLength); return true; } else return false; } int main(void) { std::string text = "XMADAMYX"; std::string result; findLongestPalindrome(text,result); std::cout<<result.c_str()<<std::endl; system("pause"); }

虽然说复杂度到达了O(n^2),但是其实还是在面试中直观的容易解答的方式,我甚为推崇,后缀树可以作为扩展的形式去描述,但是不适合编码实现。

你可能感兴趣的:(面试,String,vector,tree,扩展,联想)