5. Longest Palindromic Substring

26 篇文章 0 订阅
16 篇文章 0 订阅

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

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

 

Example:

Input: "cbbd"

Output: "bb"


1 . 我的思路:找出 s 和 s的翻转字符串的最长的共同子串,即为其最长回文字符串。方法就是以 s 为基准,将其翻转字符串分别左移 和 右移 0-n-1,然后找出其中最长的连续子串即可,但是还要考虑这种情况

"abcdasdfghjkldcba"

所以在更新最长子串的时候要比较其索引排除上面那种情况,最终时间复杂度为O(n3)。

const int maxlen = 1005;
int last_st,st,Max,cnt,mark,p = -1;
int judge(char* s,int st,int Max){
    for(int i = st,j = Max - 1;i < Max;i++,j--){
        if(s[i] != s[j]) return 0;
    }
    return 1;
}
void findMaxlen(int i,int j,int k,char* s){
    if(mark && s[i] == s[j]){
        if(cnt > Max && judge(s,st,)){
            Max = cnt;
            last_st = st;
        }
        cnt = 1;
        st = i;
        mark = 0;
    }
    else if(s[i] == s[j]) cnt++;
    else mark = 1;
    if(i - j == p - k){
        if(cnt > Max){
            Max = cnt;
            last_st = st;
        }
    }
}
char* longestPalindrome(char* s) {
    for(int i = 0;s[i] != '\0';i++) p++;
    last_st = 0,Max = 0;
    for(int k = 0;k <= p;k++){
        mark = 1,cnt = 1,st = 0;
        for(int i=k,j=p;s[i] != '\0';i++,j--){
            findMaxlen(i,j,k,s);
        }
        mark = 1,cnt = 1,st = 0;
        for(int i=0,j=p-k;i<=p-k;i++,j--){
            findMaxlen(i,j,k,s);
        }
    }
    char* ps = (char*)malloc((Max+1)*sizeof(char));
    for(int i = 0;i < Max;i++) ps[i] = s[last_st + i];
    ps[Max] = '\0';
    for(int i = 0;ps[i] != '\0';i++) printf("%c",ps[i]);

    return  ps;
}


2 . DP解法(https://leetcode.com/problems/longest-palindromic-substring/solution/):


自己写的动态规划如下:

char* longestPalindrome(char* s) {
    int n = 0,dp[1005][1005] = {0};
    int st = 0,longest = 1;
    for(int i=0;s[i] != '\0';i++){
        dp[i][i] = 1;
        n++;
    }
    for(int i=1;i < n;i++){
        dp[i-1][i] = s[i-1] == s[i];
    }
    for(int i=0;i < n - 1;i++){
        for(int j=i+2;j < n;j++){
            dp[i][j] |= dp[i+1][j-1] && s[i] == s[j];
        }
    }
    for(int i=0;i < n;i++){
        for(int j=i + longest;j<n;j++){
            if(dp[i][j]){
                longest = j - i + 1;
                st = i;
            }
        }
    }
    char* ps = (char*)malloc((longest + 1) * sizeof(char));
    for(int i = 0;i < longest;i++) ps[i] = s[st+i];
    ps[longest] = '\0';

    return  ps;
}

这个DP写的不对,比如 "abcba",按照上面的程序结果是 "bcb",因为其寻找回文字符串的顺序是不对,寻找最长的回文字符喜欢的顺序应该是由短到长,但是它是对于前 n - 1 个字符,依次确定从这个字符开始往后数1位 2 位 ....一直到末尾,这 n - i 个字符串是否是回文字符串,所以在判断较长的回文字符串的时候在其内部的回文字符串还没有被判是,就是导致较长的被判否。正确的顺序应该是,先找出所有长度为 i 的字符串之后再寻找长度位 i + 1 的字符串,参考这篇博客修改之后的程序如下:

char* longestPalindrome(char* s) {
    int n = 0,dp[1005][1005] = {0};
    int st = 0,longest = 1;
    while(s[n] != '\0') n++;
    for(int dl = 0;dl < n;dl++){
        for(int i = 0;i + dl < n;i++){
            int j = i + dl;
            if(s[i] == s[j] && (dl <= 2 || dp[i+1][j-1])){
                dp[i][j] = 1;
                if(j - i + 1 > longest){
                    longest = j - i + 1;
                    st = i;
                }
            }
        }
    }
    s[st + longest] = '\0';

    return  s + st;
}


3. 中心扩展法:寻找以每个字符为中心的最长回文字符串,有两种情况:奇数和偶数。

char* longestPalindrome(char* s) {
    int n = 0,l,r,st = 0,Max = 1;
    while(s[n] != '\0') n++;
    for(int i = 0;i < n;i++){
        l = i - 1,r = i + 1;
        while(l >= 0 && r < n && s[l] == s[r]) l--,r++;
        l++,r--;
        if(r - l + 1 > Max) st = l,Max = r - l + 1;
        l = i,r = i + 1;
        while(l >= 0 && r < n && s[l] == s[r]) l--,r++;
        l++,r--;
        if(r - l + 1 > Max) st = l,Max = r - l + 1;
    }
    s[st + Max] = '\0';
    return  s + st;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值