leetcode 5 Longest Palindromic Substring

来源:互联网 发布:知床观光协会 编辑:程序博客网 时间:2024/06/08 09:19

题目为:

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

中文为:寻找一个字符串里面最长回文字串

方法一:利用动态规划方法

更简洁的做法,使用动态规划,空间复杂度为O(N²)。做法如下:

首先,写出动态转移方程。

定义 table[ i, j ] ← true 当字串 Si … Sj 是一个回文串,否则为false。.

更新 table[ i, j ] ← ( table[ i+1, j-1 ] and Si = Sj ) ,显然,如果一个子串是回文串,并且如果从它的左右两侧分别向外扩展的一位也相等,那么这个子串就可以从左右两侧分别向外扩展一位。

其中的base case是

table[ i, i ] ← true//即为自己本身是一个长度为1的回文字串
table[ i, i+1 ] ← ( Si = Si+1 )//向右扩展一位,查看是否和自己相同,若相同table[i,i+1]=1,否则为0;

然后,看一个例子。

假设有个字符串是adade,现在要找到其中的最长回文子串。使用上面的动态转移方程,有如下的过程

按照红箭头->黄箭头->蓝箭头->绿箭头->橙箭头的顺序依次填入矩阵,通过这个矩阵记录从i到j是否是一个回文串。

char* longestPalindrome(char* s) {        int n=strlen(s);    int i;    bool table[1000][1000]={0};        int longestbegin=0;    int maxlen=1;        //将主对角线的值赋值为1,意思为自己和自己为回文数,并且回文字串长度为1    for(i=0;i<n;i++)    {        table[i][i]=1;    }        //此时,每个单个的字符左右扩展一位,如果左边的和右边的相等,则赋值为1否则为0    //例如:字符串abade,字符a向右扩展为字符b,和a不相等,那么table[0][1]=0,    //这部分仅为每个字符向有扩展一位比较,    for(i=0;i<n-1;i++)    {        if(s[i]==s[i+1])        {            table[i][i+1]=1;            maxlen=2;//最长字串增长为2            longestbegin=i;//最长字串的开始字符下表为i        }    }        for (int len = 3; len <= n; len++) //字串长度从3开始,len=3    {          for (int i = 0; i < n-len+1; i++) //i为在每一轮可以修改的个数        {              int j = i+len-1;              if (s[i] == s[j] && table[i+1][j-1]) //关键            {                  table[i][j] = true;                  longestbegin = i;                  maxlen = len;              }          }       }  char * r=(char *)malloc(sizeof(char)*(maxlen+1));for(int j=0;j<maxlen;j++){    r[j]=s[longestbegin];    longestbegin++;}r[maxlen]='\0';return r;    }


方法二:从中间向两边展开

回文字符串显然有个特征是沿着中心那个字符轴对称。比如aha沿着中间的h轴对称,a沿着中间的a轴对称。那么aa呢?沿着中间的空字符''轴对称。
所以对于长度为奇数的回文字符串,它沿着中心字符轴对称,对于长度为偶数的回文字符串,它沿着中心的空字符轴对称。
对于长度为N的候选字符串,我们需要在每一个可能的中心点进行检测以判断是否构成回文字符串,这样的中心点一共有2N-1个(2N-1=N-1 + N)。
检测的具体办法是,从中心开始向两端展开,观察两端的字符是否相同。代码如下:

//从中间向两边展开string expandAroundCenter(string s, int c1, int c2) {  int l = c1, r = c2;  int n = s.length();  while (l >= 0 && r <= n-1 && s[l] == s[r]) {    l--;    r++;  }  return s.substr(l+1, r-l-1);} string longestPalindromeSimple(string s) {  int n = s.length();  if (n == 0) return "";  string longest = s.substr(0, 1);  // a single char itself is a palindrome  for (int i = 0; i < n-1; i++) {    string p1 = expandAroundCenter(s, i, i); //长度为奇数的候选回文字符串    if (p1.length() > longest.length())      longest = p1;     string p2 = expandAroundCenter(s, i, i+1);//长度为偶数的候选回文字符串    if (p2.length() > longest.length())      longest = p2;  }  return longest;}








0 0
原创粉丝点击