5.最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba"也是一个有效答案。

示例 2:

输入: "cbbd"
输出: "bb"

这道题就是很朴素的,从每位开始向两侧判断是否回文。
以示例2为例,由于没有一个中间位。所以将字符串中插入分隔符#,每两个字符间都加入一个分隔符,之后所有的可能都可以变成奇数长度的字符串。
这道题还有一个简化方法:“马拉车算法”,即假设一个大的回文内部,存在一个小的回文值,则小的回文值可以直接从对称值开始增加,减少了一部分的重复计算。
参考资料1:https://www.cnblogs.com/grandyang/p/4475985.html
参考资料2:(很喜欢里面提到的:学好写暴力,走遍天下都不怕)https://www.cnblogs.com/ZDHYXZ/p/7697777.html

从展开的字符串如何映射回原来的字符串呢?
0 1 2 3 4 5 6
对照映射的是
# 0 # 1 # 2 #
原字符串位置*2 + 1 = 新字符串位置
新字符串起始字符位置 = 中心位置 - 单侧最长距离
则原字符串起始字符位置 = ( 中心位置 - 单侧最长距离 - 1 )/ 2
由于不同的实现方法不同,以及max表示的含义不同,以及为了隔开首位的井号,因此我最终的实现是
s.substr((max_mid - max + 2)/2,max - 1);

本地测试可通过,但是测试点ababa,leetcode报错“terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr: __pos (which is 18446744073709551614) > this->size() (which is 5)”
报错信息中,第一个__pos的值是一段乱码。原来是while循环中当i-j<0的时候,会出现未知现象。
参考资料1中,使用了最初始位置添加¥的方法,规避了该问题。而我疏忽了这一点

得到的参数s是个string类型,由于我对string类型的具体语法不熟练,所以参考了他人博客。
参考资料3:(标准C++中的string类)https://www.cnblogs.com/aminxu/p/4686320.html
参考资料4:(string的遍历)https://blog.csdn.net/stpeace/article/details/50406627

完整代码:

#include
#include
#include
#include
#include
#include

using namespace std;

string longestPalindrome(string s) {
    if(s == ""){
        return s;
    }
    string fold = "#";
    int i,j,len,max,max_mid,tmp_mid,tmp_r;
    for(i = 0; i < s.size(); i++){
        fold += s[i];
        fold += '#'; 
    }
    len = fold.size();
    vector value(len, 0); //此行学自参考资料1 
    max = 2;
    max_mid = tmp_mid = tmp_r = 1;
    for(i = 2; i < len; i++){
        value[i] = (tmp_r > i)? min(value[tmp_mid *2 - i], tmp_r - i): 1;
        j = value[i];
        while(fold[i + j] == fold[i - j]){
            j++;
        }
        value[i] = j;
        if(i + j > tmp_r){
            tmp_r = i + j;
            tmp_mid = i;
        }
        if(j >= max){
            max = j;
            max_mid = i;
        }
//      cout << i << " " << fold[i] << endl;
//      cout << max << "   mid:" << max_mid << endl;
    }
//  cout << fold << endl;
//  cout << max_mid - max + 2 << endl;
    return s.substr((max_mid + 2 - max)/2,max - 1);
}

int main(){
    string s = "a";
    s = longestPalindrome(s);
    cout << s << endl;
    return 0;
}

你可能感兴趣的:(5.最长回文子串)