【Leetcode】Longest Palindromic Substring Part

来源:互联网 发布:司马懿之军事联盟 知乎 编辑:程序博客网 时间:2024/05/23 23:28

问题

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.

解法1:

O(N^2) 的算法复杂度的算法就不多说了,无非是遍历I,J,取得一个子串,并对这个字串进行判定,是否是回文串。遍历复杂度为O(N^2),判定复杂度为O(N)(前后指针),所以复杂度为O(N^2).

解法2:

http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html

根据他的解法,我能够理解他的想法,遍历一遍,取得中数,并向四周扩散,最后得出以此为中数,它最大能够扩充到多大。

当时我就有一个疑问:为什么要加#$^这些符号?

所以我打算不用符号实现一遍他的想法:

class Solution {public:    string longestPalindrome(string s) {        int i =0;        int C = 0;        int R = 0;        int L = 0;        int i_mirror = 0;                /* init P */        int *P = new int[s.length()];        for (i = 0 ; i < s.length(); i++) {            P[i] = 0;        }                /* for every charactor */        for (i = 1 ; i < s.length() - 1; i++) {            i_mirror = 2*C - i;            P[i] = R > i ? min(R-i , P[i_mirror]): P[i];                        int expand = (P[i] -1)/2;            while (1 ){                expand ++;                int leftExpandIndex = i - expand;                int rightExpandIndex = i + expand;                if (leftExpandIndex == 0 || rightExpandIndex == s.length() -1) {                    expand --;                    break;                }                if (s[leftExpandIndex] != s[rightExpandIndex]) {                    expand --;                    break;                }                            }            P[i] = expand * 2 +1;                        if (i + expand > R) {                C = i;                L = i - expand;                R = i + expand;            }        }                int maxLen = 0;        int centelIndex = 0;        for (i = 0 ; i < s.length(); i++) {            if(maxLen < P[i])            {                centelIndex = i;                maxLen = P[i];            }        }        int leftPosition = centelIndex - ((maxLen -1)/2);        return s.substr(leftPosition , maxLen);                    }

最后我得出来的结论是,奇数回文数能够正确的被解答出来,而偶数的不行。所以在这里我就明白了,他为何要使用特殊符号了。

使用的用意很简单,举个例子:

1. 偶数个回文数:

#a#b#c#c#b#a#

其中以最中间的那个#为中数,左右分别有6个数,正好6 是 abccba 6个数。

2. 奇数个回文数:

#a#b#c#b#a#

其中以c为中数,分别左右有5个数,正好 abcba 也是5个数。


这是一个非常巧妙的解法,当我实现以上的算法的时候,坦白讲我也想再偶数回文数中塞一个数,我相信作者也是通过这个启发到最后他的解法。

修正之后的代码:

string translate(string s){    string rs("^#");    for (int i = 0; i  < s.length(); i++) {        rs.push_back(s[i]);        rs.push_back('#');    }    rs.push_back('$');    //cout<<rs<<endl;    return rs;}class Solution {public:    string longestPalindrome(string s) {        int i =0;        int C = 0;        int R = 0;        int L = 0;        int i_mirror = 0;                string rs= translate(s);                /* init P */        int *P = new int[rs.length()];        for (i = 0 ; i < rs.length(); i++) {            P[i] = 0;        }                /* for every charactor */        for (i = 1 ; i < rs.length() - 1; i++) {            i_mirror = 2*C - i;            P[i] = R > i ? min(R-i , P[i_mirror]): 0;                        while (rs[i - P[i] -1] == rs[i + P[i] +1] ){                P[i]++;            }                        if (i + P[i] > R) {                C = i;                L = i - P[i];                R = i + P[i];            }        }                int maxLen = 0;        int centelIndex = 0;        for (i = 0 ; i < rs.length(); i++) {            if(maxLen < P[i])            {                centelIndex = i;                maxLen = P[i];            }        }        int leftPosition = (centelIndex - 1 - maxLen)/2;        //cout<<maxLen<<endl;        return s.substr(leftPosition , maxLen);    }};

分析

分析就不讲了,文中有提到,慢慢看。

总结

有时候需要通过添加某些辅助的数据来帮助自己简化逻辑。在第一个算法中其实可以加入偶数判定,也并非完全不可能实现,比较麻烦而已。

0 0
原创粉丝点击