Algorithm --> 最长回文子串

1、中心扩展

中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)

但是要考虑两种情况:

1、像aba,这样长度为奇数。

2、想abba,这样长度为偶数。
代码如下:
string findLongestPalindrome(string &s)
{
    const int length=s.size();
    int maxlength=0;
    int start;

    for(int i=0;i<length;i++)//长度为奇数
    {
        int j=i-1,k=i+1;
        while(j>=0&&k<length&&s.at(j)==s.at(k))
        {
            if(k-j+1>maxlength)
            {
                maxlength=k-j+1;
                start=j;
            }
            j--;
            k++;
        }
    }

    for(int i=0;i<length;i++)//长度为偶数
    {
        int j=i,k=i+1;
        while(j>=0&&k<length&&s.at(j)==s.at(k))
        {
            if(k-j+1>maxlength)
            {
                maxlength=k-j+1;
                start=j;
            }
            j--;
            k++;
        }
    }
    if(maxlength>0)
        return s.substr(start,maxlength);
    return NULL;
}
 
 
 
2、动态规划
 
有母串s,我们用c[i, j] = 1表示子串s[i..j]为回文子串,空间和算法复杂度也是O(N^2)。那么就有递推式:
c[i,j]={ c[i+1,j−1],   if s[i]=s[j]
               0if s[i]≠s[j]

递推式表示在s[i] = s[j]情况下,如果s[i+1..j-1]是回文子串,则s[i..j]也是回文子串;如果s[i+1..j-1]不是回文子串,则s[i..j]也不是回文子串。

初始状态:

    c[i][i] = 1
    c[i][i+1] = 1 if s[i] == s[i+1]

上述式子表示单个字符、两个字符均是回文串[j]

int longestPald(char *str) {
    int len = strlen(str);
    int c[maxLen][maxLen];
    int i,j;
    int longest = 1;
    
    assert(str != NULL);
    if(len == 1) {
        return 1;
    }
      //initialization
    for(i = 0; i < len; i++) {
        c[i][i] = 1;
        if(str[i] == str[i+1])
           c[i][i+1] = 1;
    }

    for(i = 0; i < len; i++) {
        for(j = i+2; j <= len; j++) {
            if(str[i] == str[j]) {
                c[i][j] = c[i+1][j-1];
                //find longest palindrome substring
                if(c[i][j]) { 
                    int n = j - i + 1;
                    if(longest < n)
                        longest = n;                
                }
            } else {
                c[i][j] = 0;
            }
        }
    }
    return longest;
}

3、暴力法

最容易想到的就是暴力破解,求出每一个子串,之后判断是不是回文,找到最长的那个。

求每一个子串时间复杂度O(N^2),判断子串是不是回文O(N),两者是相乘关系,所以时间复杂度为O(N^3)。

string findLongestPalindrome(string &s)
{
    int length=s.size();//字符串长度
    int maxlength=0;//最长回文字符串长度
    int start;//最长回文字符串起始地址
for(int i=0;i<length;i++)//起始地址 for(int j=i+1;j<length;j++)//结束地址 { int tmp1,tmp2; for(tmp1=i,tmp2=j;tmp1<tmp2;tmp1++,tmp2--)//判断是不是回文 { if(s.at(tmp1)!=s.at(tmp2)) break; } if(tmp1>=tmp2&&j-i>maxlength) { maxlength=j-i+1; start=i; } } if(maxlength>0) return s.substr(start,maxlength);//求子串 return NULL; }

4、Manacher法(待续)

原文地址:https://www.cnblogs.com/jeakeven/p/4564809.html