Longest Palindromic Substring

来源:互联网 发布:mysql修改列名 语句 编辑:程序博客网 时间:2024/06/02 05:29

                                                                                          最长回文子序列——leetcode5

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

tag:string

Example:

Input: "babad"Output: "bab"Note: "aba" is also a valid answer.

Example:

Input: "cbbd"Output: "bb"
本题是求解一个字符串的最长子序列(注意子序列必须是相连的,不能相隔)

有多种方法解决此题

一.暴力法求解

用了两个嵌套循环,循环中还有一个判断是否为回文序列的O(n)算法,最终的时间复杂度是O(n^3),这道题也不出意料地TLE了

代码如下:

class Solution {public:    string longestPalindrome(string s) {        string ret="";        int ans=0;        int left,right;        int start;                for(int i=0;i<s.size();i++)        for(int j=i;j<s.size();j++)        {             left=i;             right=j;            bool flag=true;                        while(left<=right)            {                if(s[left]==s[right])                {                    left++;                    right--;                }                else                 {                    flag=false;                    break;                }            }            if(flag)            {                int len=j-i+1;                if(len>ans)                {                    ans=len;                    start=i;                }            }                                   }        ret=s.substr(start,ans);                return ret;    }};
二.dp


我们可以从题目中得知a[i][j]=a[i+1][j-1]&&(s[i]==s[j])

时间复杂度为O(n^2),额外的空间O(n^2)

代码如下:

class Solution {public:       string longestPalindrome(string s) {         bool a[1010][1010]={false};        int len=1;        int start=0;        string str="";      for(int i=0;i<s.size();i++)       {           a[i][i]=true;           if(i<s.size()-1&&s[i]==s[i+1])           {               a[i][i+1]=true;               len=2;               start=i;           }                               }       for(int length=3;length<=s.size();length++)        for(int i=0;i+length<=s.size();i++)        {            int j=i+length-1;            if(a[i+1][j-1]&&s[i]==s[j])            {                a[i][j]=true;                start=i;                len=length;            }                    }        str=s.substr(start,len);        return str;    }};

三:中心拓展法


用这种方法我们需要分回文序列的长度为奇数和偶数分别考虑,时间复杂度也为O(n^2)


这种方法也比较好理解,直接看代码就可以了

class Solution {public:       string longestPalindrome(string s) {       int start=0;       int len=1;       for(int i=0;i<s.size();i++)        {            int left=i-1;            int right=i+1;            int length=1;            while(left>=0&&right<s.size()&&s[left]==s[right])            {                length+=2;                if(length>len)             {                len=length;                start=left;             }                                                        left--;                     right++;                                                                                        }                    }        for(int i=0;i<s.size();i++)        {            int left=i;            int right=i+1;            int length=0;            while(left>=0&&right<s.size()&&s[left]==s[right])            {                length+=2;                                  if(length>len)                {                len=length;                start=left;                }                                                        left--;                    right++;                                                                                    }                  }        string ret=s.substr(start,len);        return ret;    }};

四:Manacher法(优)

这种方法只能处理奇数的 所以我们可以把所有字符中间加上特殊符号"#",最后再去掉就可以了。(注意:在初始字符串的首尾都要加上"#"  例如:”abb“ 应改为”#a#b#b#“ 若只改为“a#b#b” 则会出现错误 正确答案应为“bb",但第二种改法右侧被限制住了,无法向右拓展,”b#b"和“#b#"的长度一样,但”#b#"先出现,所以错误答案为“b”)

Manacher法不太好描述,我是通过这篇文章学习到的

rad数组存储以下标i为中心的回文子序列的半径

该方法的时间复杂度为O(n)

代码如下:

class Solution {public:       string longestPalindrome(string s) {        int len=s.size();     for(int i=0,k=0;i<len+1;i++)     {         s.insert(k,"#");         k+=2;     }     len=2*len+1;         int *rad=new int[len]();     rad[0]=0;     for(int i=1,j=1,k;i<len;i=i+k)     {         while(s[i-j]==s[i+j]&&i-j>=0&&i+j<len)         j++;         rad[i]=j-1;         for(k=1;k<=rad[i]&&rad[i]-k!=rad[i-k];k++)           rad[i+k]=min(rad[i-k],rad[i]-k);          j=max(j-k,0);              }     int center=0;     int length=0;     for(int i=0;i<len;i++)     {         if(rad[i]>length){         length=rad[i];         center=i;         }     }     string ret=s.substr(center-length,length*2+1);     int l=ret.size();     for(int i=0,k=0;i<l+1;i++)     {         if(ret[k]=='#')ret.erase(k,1);         k++;     }     return ret;    }};


原创粉丝点击