[DP/Manacher]最长回文子串(经典DP)_Short

------------6.11更新-----------
明天(tuo yan)继续把 Basic & Tall刷了,改日再战

------------Original------------
为什么说这个是个经典DP呢,它经典到与最长公共子序列一样经典.
几万种变体:
这里我要来归纳一下,免得有人像我一样被虐成狗.

Short - 求给定串的最长回文子串
Basic - 给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数. ---->这是个回文子序列,不是回文子串,别尼玛搞混了
Tall.. - 给定一个数字串digit_str,每次操作可以把相邻2个数字相加并替换掉这2个数字,问至少操作几次可以得到一个回文数字串?输出最少操作次数.
(to be added)

Short(超小杯)

基本的最长回文子串.
有暴力/DP/Manacher三种算法.

其中Manacher马拉车算法是利用了回文串的特性,做到了尽可能利用已知信息,达到了O(N)时间复杂度.

基本上搜索一下都可以找到很多信息.

暴力

不多说,如果笔试肯定超时.
枚举子串时可以按照子串的长度从1 .. str.size()来枚举.
时间复杂度 - O(N3),网上大多数都说O(N3),但我觉得应该是在O(N2)和O(N3)之间.------------->好好地估算过了确实是个O(N3)级数.(只不过这个乘了一个`x/1`的系数,无关紧要了反正还是O(N3))

DP法

第一时间想到用F[i,j]表示i..j的最长回文子串长度.马上就有F[0,l-1]就是这里需要求的整个串的最长回文子串长度.

  • 错误的DP状态转移方程
    我第一时间写下了这样的转移方程:
      F[i,j] = max { F[i+1, j-1] + 2 ----- if str[i] == str[j] ///fatal error here:如果i+1..j-1非回文但又有str[i] == str[j]怎么办?
                     F[i+1,j]        ----- otherwise1
                     F[i,j-1]        ----- otherwise2
                    }
    

错误的点正是这里,F[i,j] = F[i+1,j-1]+2的条件是比较严格的.

  • 正确的DP状态转移方程 0x1
      F[i,j] = max { F[i+1, j-1] + 2 ----- if str[i] == str[j] && F[i+1, j-1] == j-1-(i+1)+1 ////如果i+1..j-1非回文但又有str[i] == str[j]怎么办?
                     F[i+1,j]        ----- otherwise1
                     F[i,j-1]        ----- otherwise2
                    }
    

或者是网上其他人给的true/false矩阵,然后需要2个变量每次更新一下最长子串的长度和起始点.

  • 正确的DP状态转移方程 0x2
      isP[i,j] = {
                    isP[i+1,j-1] ----- if str[i] == str[j]
                    false        ----- otherwise
                 }
    
  • DP的填表方向/初始状态 ---- 不多说
Manacher法

也不多说,这个网上有很多详解的.

实现
  • 代码()
    有兴趣的同学一起来搞:<a href = https://github.com/exctPuzzles/exctpuzzs/blob/master/solutions/algs/max_plalindrome_substr.cc>github_page</a>

include <cstdio>

#include <string>
using namespace std;
#define Max(a,b) ((a) > (b) ? (a):(b))
#define Min(a,b) ((a) < (b) ? (a):(b))
#define SIZE 1005
//#define DBG_1
#define DBG_2
string::size_type F[SIZE][SIZE];//the length array
//auto init to zero
string::size_type ST[SIZE][SIZE];//the start_ofs array
class Solution {
public:
    bool isP(string &x, string::size_type st, string::size_type len){
        string::size_type ed = st + len - 1;
        while(st < ed){
            if(x[st] != x[ed]){
                return false;
            }
            st++;ed--;
        }
        return true;
    }
    string max_plalindrome_substr_bf(string x){
    //just simply find all substring & see if plalindrome.
    //time complexity - O(N^3)
    //a little bit optimize
        string::size_type l = x.size(), i, st, max_l = 1, st_l;
        for(i = 2; i <= l;i++){
            for(st = 0; st + i - 1 < l ; st++){
                if(max_l >= i){
                    break;
                }
                if(isP(x, st, i)){
                    max_l = i;
                    st_l = st;
                }
            }
        }
#ifdef DBG_2
        for(i = 0; i < st_l; i++){
            printf(" ");
        }
        printf("%s\n", x.substr(st_l, max_l).c_str());
#endif      
        return x.substr(st_l, max_l);
    }
    
    string max_plalindrome_substr_dp(string x){
    //
    //time complexity - O(N^2) , space complexity - O(N^2)
    //
        string::size_type st_l, max_l, l = x.size(), i, st, ed;
        string::size_type a,b,c;
        for(i = 0; i < l; i++){
            F[i][i] = 1;
            ST[i][i] = i;
        }
        for(i = 2; i <= l; i++){//for every substring's length,direction to fill the DP array
            for(st = 0; (ed = st + i - 1) < l; st++){
                //a = x[st] == x[ed] ? F[st + 1][ed - 1] + 2 : 0;/////a fatal bug here
                a = x[st] == x[ed] && F[st + 1][ed - 1] == ed - 1 - st? F[st + 1][ed - 1] + 2 : 0;//the situation left for b&c
                b = F[st + 1][ed];
                c = F[st][ed - 1];
                if(a > b){
                    if(a > c){
                        F[st][ed] = a;
                        ST[st][ed] = st;
                    }else{
                        F[st][ed] = c;
                        ST[st][ed] = ST[st][ed - 1];
                    }    
                }else{
                    if(b > c){
                        F[st][ed] = b;
                        ST[st][ed] = ST[st + 1][ed];
                    }else{
                        F[st][ed] = c;
                        ST[st][ed] = ST[st][ed - 1];//bug fix
                    }
                }
            }
        }
#ifdef DBG_1
        for(i = 0; i < l; i++){
            for(string::value_type j = 0; j < l; j++){
                printf("%ld ", F[i][j]);
            }
            printf("\n");
        }
#endif      
#ifdef DBG_2
        for(i = 0; i < ST[0][l-1]; i++){
            printf(" ");
        }
        printf("%s\n", x.substr(ST[0][l-1], F[0][l-1]).c_str());
#endif
        return x.substr(ST[0][l-1], F[0][l-1]);

    }
    
    bool isP_arr[SIZE][SIZE];
    
    string max_plalindrome_substr_dp2(string s){
        string::size_type i, l = s.size(), st, ed, max_l = 1, max_st;
        for(i = 0; i < l; i++){//len = 1
            isP_arr[i][i] = true;
            isP_arr[i+1][i] = true;
        }
        for(i = 2; i <= l; i++){
            for(st = 0; (ed = st + i - 1) < l; st++){
                isP_arr[st][ed] = s[st] == s[ed] ? isP_arr[st+1][ed-1] : false;
                if(isP_arr[st][ed] && i > max_l){
                    max_l = i;
                    max_st = st;
                }
            }
        }
#ifdef DBG_2
        for(i = 0; i < max_st; i++){
            printf(" ");
        }
        printf("%s\n", s.substr(max_st, max_l).c_str());
#endif      
        return s.substr(max_st, max_l);
    }
#define dou_SIZE 2010
    string max_plalindrome_substr_mnc(string s){
        string tmp(s);
        string::size_type po, r_mx, Len[dou_SIZE], i, j, mx_iter, l, rt, lt;
        for(i = 0; i <= s.size(); i++){
            tmp.insert( 2 * i, "#");
        }//convert the string to #s#t#r#i#n#g#
        
//      printf("%s\n", tmp.c_str());
        l = tmp.size();
        po = 0;
        r_mx = 0;
        string::size_type start_point, mirr, length;
        for(i = 0; i < l; i++){//calc Len[i]
            if(i < r_mx){
                mirr = 2 * po - i;
                if(Len[mirr] >= r_mx - i + 1){
                    Len[i] = r_mx - i + 1;
                    start_point = r_mx - i + 1;
                }else{
                    Len[i] = Len[mirr];
                    continue;
                }
            }else{
                Len[i] = 1;////
                start_point = 1;
            }
            
            mx_iter = Min(i - 0 + 1, l - 1 - i + 1 ) - 1;
            for(j = start_point/**/; j <= mx_iter; j++){
                lt = i - j;
                rt = i + j;
                if(tmp[lt] == tmp[rt]){
                    Len[i]++;
                    if(Len[i] > r_mx - po + 1){
                        po = i;
                        r_mx = po + Len[i] - 1;
                    }
                }else{
                    break;
                }
            }
        }
        if(tmp[po] == '#'){
            start_point = po/2 - (Len[po] - 1)/2;
            length = (Len[po] - 1);
        }else{
            length = (Len[po] - 1);
            start_point = (po-1)/2 - (length - 1)/2;            
        }
#ifdef DBG_2
        for(i = 0; i < start_point; i++){
            printf(" ");
        }
        printf("%s\n", s.substr(start_point, length).c_str());
#endif
        return s.substr(start_point, length);
    }
    
    string longestPalindrome(string s) {
        string ret;
#ifdef DBG_2
        printf("%s\n", s.c_str());
        ret = max_plalindrome_substr_bf(s);
        printf("==============================================\n");
        printf("%s\n", s.c_str());
        max_plalindrome_substr_dp(s);
        printf("==============================================\n");
        printf("%s\n", s.c_str());
        max_plalindrome_substr_dp2(s);
        
        printf("==============================================\n");
        printf("%s\n", s.c_str());
        max_plalindrome_substr_mnc(s);
#endif  
        return ret;
    }
};
  
#include <iostream>
int main()
{
    Solution s;
    string str;
    while(getline(cin, str)){
        s.longestPalindrome(str);
        //printf("longest palindromic substr - %s\n", s.longestPalindrome(str2).c_str());
    }
    return 0;
}
```
  • 测试 - leetcode/5.longest palindromic substring 通过.
echo "zgtklhfzomzjckwmluvivvcmhjrwkuvcjrxojobpdedpamdshcwwsetfbacvonecrdvugeibglvhxuymjvoryqjwullvzglqazxrdmczyvbgakjagttrezmvrlptiwoqkrtxuroeqmryzsgokopxxdpbejmtwvpnaqrgqladdszhdwxfckmewhdvihgvacueqhvwvjxoitlpfrckxkuksaqzjpwgoldyhugsacflcdqhifldoaphgdbhaciixouavqxwlghadmfortqacbffqzocinvuqpjthgekunjsstukeiffjipzzabkuiueqnjgkuiojwbjzfynafnlcaryygqjfixaoeowhkxkbsnpsvnbxuywfxbnuoemxynbtgkqtjvzqikbafjnpbeirxxrohhnjqrbqqzercqcrcswojyylunuevtdhamlkzqnjrzibwckbkiygysuaxpjrgjmurrohkhvjpmwmmtpcszpihcntyivrjplhyrqftghglkvqeidyhtmrlcljngeyaefxnywpfsualufjwnffyqnpitgkkyrbwccqggycrvoocbwsdbftkigrkcbojuwwctknzzmvhbhbfzrqwzllulbabztqnznkqdyoqnrxhwavqhzyzvmmmphzxbikpharseywpfsqyybkynwbdrgfsaxduxojcdqcjuaywzbvdjgjqtoffasiuhvxcaockebkuxpiomqmtvsqhnyxfjceqevqvnapbk " | ./test > 1.txt
zgtklhfzomzjckwmluvivvcmhjrwkuvcjrxojobpdedpamdshcwwsetfbacvonecrdvugeibglvhxuymjvoryqjwullvzglqazxrdmczyvbgakjagttrezmvrlptiwoqkrtxuroeqmryzsgokopxxdpbejmtwvpnaqrgqladdszhdwxfckmewhdvihgvacueqhvwvjxoitlpfrckxkuksaqzjpwgoldyhugsacflcdqhifldoaphgdbhaciixouavqxwlghadmfortqacbffqzocinvuqpjthgekunjsstukeiffjipzzabkuiueqnjgkuiojwbjzfynafnlcaryygqjfixaoeowhkxkbsnpsvnbxuywfxbnuoemxynbtgkqtjvzqikbafjnpbeirxxrohhnjqrbqqzercqcrcswojyylunuevtdhamlkzqnjrzibwckbkiygysuaxpjrgjmurrohkhvjpmwmmtpcszpihcntyivrjplhyrqftghglkvqeidyhtmrlcljngeyaefxnywpfsualufjwnffyqnpitgkkyrbwccqggycrvoocbwsdbftkigrkcbojuwwctknzzmvhbhbfzrqwzllulbabztqnznkqdyoqnrxhwavqhzyzvmmmphzxbikpharseywpfsqyybkynwbdrgfsaxduxojcdqcjuaywzbvdjgjqtoffasiuhvxcaockebkuxpiomqmtvsqhnyxfjceqevqvnapbk
                                       pdedp
==============================================
zgtklhfzomzjckwmluvivvcmhjrwkuvcjrxojobpdedpamdshcwwsetfbacvonecrdvugeibglvhxuymjvoryqjwullvzglqazxrdmczyvbgakjagttrezmvrlptiwoqkrtxuroeqmryzsgokopxxdpbejmtwvpnaqrgqladdszhdwxfckmewhdvihgvacueqhvwvjxoitlpfrckxkuksaqzjpwgoldyhugsacflcdqhifldoaphgdbhaciixouavqxwlghadmfortqacbffqzocinvuqpjthgekunjsstukeiffjipzzabkuiueqnjgkuiojwbjzfynafnlcaryygqjfixaoeowhkxkbsnpsvnbxuywfxbnuoemxynbtgkqtjvzqikbafjnpbeirxxrohhnjqrbqqzercqcrcswojyylunuevtdhamlkzqnjrzibwckbkiygysuaxpjrgjmurrohkhvjpmwmmtpcszpihcntyivrjplhyrqftghglkvqeidyhtmrlcljngeyaefxnywpfsualufjwnffyqnpitgkkyrbwccqggycrvoocbwsdbftkigrkcbojuwwctknzzmvhbhbfzrqwzllulbabztqnznkqdyoqnrxhwavqhzyzvmmmphzxbikpharseywpfsqyybkynwbdrgfsaxduxojcdqcjuaywzbvdjgjqtoffasiuhvxcaockebkuxpiomqmtvsqhnyxfjceqevqvnapbk
                                       pdedp
==============================================
zgtklhfzomzjckwmluvivvcmhjrwkuvcjrxojobpdedpamdshcwwsetfbacvonecrdvugeibglvhxuymjvoryqjwullvzglqazxrdmczyvbgakjagttrezmvrlptiwoqkrtxuroeqmryzsgokopxxdpbejmtwvpnaqrgqladdszhdwxfckmewhdvihgvacueqhvwvjxoitlpfrckxkuksaqzjpwgoldyhugsacflcdqhifldoaphgdbhaciixouavqxwlghadmfortqacbffqzocinvuqpjthgekunjsstukeiffjipzzabkuiueqnjgkuiojwbjzfynafnlcaryygqjfixaoeowhkxkbsnpsvnbxuywfxbnuoemxynbtgkqtjvzqikbafjnpbeirxxrohhnjqrbqqzercqcrcswojyylunuevtdhamlkzqnjrzibwckbkiygysuaxpjrgjmurrohkhvjpmwmmtpcszpihcntyivrjplhyrqftghglkvqeidyhtmrlcljngeyaefxnywpfsualufjwnffyqnpitgkkyrbwccqggycrvoocbwsdbftkigrkcbojuwwctknzzmvhbhbfzrqwzllulbabztqnznkqdyoqnrxhwavqhzyzvmmmphzxbikpharseywpfsqyybkynwbdrgfsaxduxojcdqcjuaywzbvdjgjqtoffasiuhvxcaockebkuxpiomqmtvsqhnyxfjceqevqvnapbk
                                       pdedp
==============================================
zgtklhfzomzjckwmluvivvcmhjrwkuvcjrxojobpdedpamdshcwwsetfbacvonecrdvugeibglvhxuymjvoryqjwullvzglqazxrdmczyvbgakjagttrezmvrlptiwoqkrtxuroeqmryzsgokopxxdpbejmtwvpnaqrgqladdszhdwxfckmewhdvihgvacueqhvwvjxoitlpfrckxkuksaqzjpwgoldyhugsacflcdqhifldoaphgdbhaciixouavqxwlghadmfortqacbffqzocinvuqpjthgekunjsstukeiffjipzzabkuiueqnjgkuiojwbjzfynafnlcaryygqjfixaoeowhkxkbsnpsvnbxuywfxbnuoemxynbtgkqtjvzqikbafjnpbeirxxrohhnjqrbqqzercqcrcswojyylunuevtdhamlkzqnjrzibwckbkiygysuaxpjrgjmurrohkhvjpmwmmtpcszpihcntyivrjplhyrqftghglkvqeidyhtmrlcljngeyaefxnywpfsualufjwnffyqnpitgkkyrbwccqggycrvoocbwsdbftkigrkcbojuwwctknzzmvhbhbfzrqwzllulbabztqnznkqdyoqnrxhwavqhzyzvmmmphzxbikpharseywpfsqyybkynwbdrgfsaxduxojcdqcjuaywzbvdjgjqtoffasiuhvxcaockebkuxpiomqmtvsqhnyxfjceqevqvnapbk
                                       pdedp
想做成一件事最好的办法就是——做他
Just father Fucking Do it.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容