LeetCode005 Longest Palindromic Substring

来源:互联网 发布:cf显示网络异常win7 编辑:程序博客网 时间:2024/05/22 06:39
详细见:leetcode.com/problems/longest-palindromic-substring/

说明: manacher

Java Solution: github

package leetcode;/* * 假定存在唯一一个最长子序列 */public class P005_LongestPalindromicSubstring {public static void main(String[] args) {System.out.println(new Solution4().longestPalindrome("abad"));}/* * 毫无疑问manacher(不会拼错了吧) * 35.45% * 特别慢 * 57ms */static class Solution {private final char sign = '#';    public String longestPalindrome(String s) {    if (s == null || s.length() == 0)    return "";        char[] m = new char[(s.length() << 1) + 1];        for (int i = 0; i != m.length; i ++)        m[i] = (i & 0x1) == 0 ? sign : s.charAt(i >>> 1);        int[] r = new int[m.length];        r[0] = 0; r[1] = 1;        int maxr = 2, core = 1, maxindex = 1;        for (int i = 2; i != m.length; i ++) {        if (i >= maxr) {        int newr = 1;        while (i > newr - 1 && i + newr < m.length && m[i + newr] == m[i - newr])        newr ++;        r[i] = newr - 1;        maxr = i + r[i];        core = i;        } else {        int j = (core << 1) - i;        if (r[j] + i < maxr) {        r[i] = r[j];        } else {        int newr = 1;        while (i > newr - 1 && i + newr < m.length && m[i + newr] == m[i - newr])        newr ++;        r[i] = newr - 1;        maxr = i + r[i];        core = i;        }        }        if (r[maxindex] < r[i])        maxindex = i;        if (maxr == m.length)        break;        }        StringBuilder st = new StringBuilder();        for (int i = maxindex - r[maxindex]; i != maxindex + r[maxindex] + 1; i ++)        if ((i & 0x1) == 1)        st.append(m[i]);        return st.toString();    }}/* * 没有使用StringBuilder * 40.94% * 43 ms */static class Solution2 {private final char sign = '#';    public String longestPalindrome(String s) {    if (s == null || s.length() == 0)    return "";        char[] m = new char[(s.length() << 1) + 1];        for (int i = 0; i != m.length; i ++)        m[i] = (i & 0x1) == 0 ? sign : s.charAt(i >>> 1);        int[] r = new int[m.length];        r[0] = 0; r[1] = 1;        int maxr = 2, core = 1, maxindex = 1;        for (int i = 2; i != m.length; i ++) {        if (i >= maxr) {        int newr = 1;        while (i > newr - 1 && i + newr < m.length && m[i + newr] == m[i - newr])        newr ++;        r[i] = newr - 1;        maxr = i + r[i];        core = i;        } else {        int j = (core << 1) - i;        if (r[j] + i < maxr) {        r[i] = r[j];        } else {        int newr = 1;        while (i > newr - 1 && i + newr < m.length && m[i + newr] == m[i - newr])        newr ++;        r[i] = newr - 1;        maxr = i + r[i];        core = i;        }        }        if (r[maxindex] < r[i])        maxindex = i;        if (maxr == m.length)        break;        }        int len = m[maxindex] == sign ?  ( (r[maxindex] + 1) >>> 1 ) << 1 : ( ( r[maxindex] >>> 1) << 1 ) + 1;        char[] ans = new char[len];        int j = 0;        for (int i = maxindex - r[maxindex]; i != maxindex + r[maxindex] + 1; i ++)        if ((i & 0x1) == 1)        ans[j ++] = m[i];        return new String(ans);    }}/* * 不用m char 数组 * 75ms * 27.05%  */static class Solution3 {private final char sign = '#';    public String longestPalindrome(String s) {    if (s == null || s.length() == 0)    return "";        int len = (s.length() << 1) + 1;        int[] r = new int[len];        r[0] = 0; r[1] = 1;        int maxr = 2, core = 1, maxindex = 1;        for (int i = 2; i != len; i ++) {        if (i >= maxr) {        int newr = 1;        while (i > newr - 1 && i + newr < len && getIndexOfM(s, i + newr) == getIndexOfM(s, i - newr))        newr ++;        r[i] = newr - 1;        maxr = i + r[i];        core = i;        } else {        int j = (core << 1) - i;        if (r[j] + i < maxr) {        r[i] = r[j];        } else {        int newr = 1;        while (i > newr - 1 && i + newr < len && getIndexOfM(s, i + newr) == getIndexOfM(s, i - newr))        newr ++;        r[i] = newr - 1;        maxr = i + r[i];        core = i;        }        }        if (r[maxindex] < r[i])        maxindex = i;        if (maxr == len)        break;        }        len = getIndexOfM(s, maxindex) == sign ?  ( (r[maxindex] + 1) >>> 1 ) << 1 : ( ( r[maxindex] >>> 1) << 1 ) + 1;        char[] ans = new char[len];        int j = 0;        for (int i = maxindex - r[maxindex]; i != maxindex + r[maxindex] + 1; i ++)        if ((i & 0x1) == 1)        ans[j ++] = getIndexOfM(s, i);        return new String(ans);    }    char getIndexOfM(String s, int i) {    if ((i & 0x1) == 0)    return sign;    else    return s.charAt(i >>> 1);    }}/* * 41 ms * 42.07% */static class Solution4 {private final char sign = '#';    public String longestPalindrome(String s) {    if (s == null || s.length() == 0)    return "";        char[] m = new char[(s.length() << 1) + 1];        for (int i = 0; i != m.length; i ++)        m[i] = (i & 0x1) == 0 ? sign : s.charAt(i >>> 1);        int[] r = new int[m.length];        r[0] = 0; r[1] = 1;        int maxr = 2, core = 1, maxindex = 1;        for (int i = 2; i != m.length; i ++) {        if (i >= maxr) {        int newr = 1;        while (i > newr - 1 && i + newr < m.length && m[i + newr] == m[i - newr])        newr ++;        r[i] = newr - 1;        maxr = i + r[i];        core = i;        } else {        int j = (core << 1) - i;        if (r[j] + i < maxr) {        r[i] = r[j];        } else {        int newr = 1;        while (i > newr - 1 && i + newr < m.length && m[i + newr] == m[i - newr])        newr ++;        r[i] = newr - 1;        maxr = i + r[i];        core = i;        }        }        if (r[maxindex] < r[i])        maxindex = i;        if (maxr == m.length)        break;        }        return s.substring((maxindex - r[maxindex]) >>> 1, (maxindex + r[maxindex]) >>> 1);    }}}


C Solution: github

/*    url: leetcode.com/problems/longest-palindromic-substring/    85ms 42.99%*/#include <stdlib.h>#include <stdio.h>#include <string.h>char _access_char_array(char* s, int i) {    if (i % 2 == 0) return '\0';    return *(s + i / 2);}char* longestPalindrome(char* s) {    int n = strlen(s);    int ma_n = 2 * n + 1;    int ma_i = 0;    int ma_li = 0;    int ma_mi = 0;    int ma_mt = 0;    int l = 0, r = 0, i = 0, j = 0;    int * ma_r = NULL;    int ma_an = 0;    char * answer = NULL;    //manacher    ma_r = (int *) malloc(sizeof(int) * ma_n);    for (ma_i = 0; ma_i < ma_n; ma_i ++)        *(ma_r + ma_i) = 0;    for (ma_i = 0; ma_i < ma_n; ma_i ++) {        if (ma_mt >= ma_n - 1) break;        ma_mi = 2 * ma_li - ma_i;        if (ma_i >= ma_mt || (ma_i + *(ma_r + ma_mi) == ma_mt)) {            l = ma_i;            r = ma_i;            while ((l - 1) > -1 && (r + 1) < ma_n && _access_char_array(s, l - 1) == _access_char_array(s, r + 1)) {                l --;                r ++;            }            *(ma_r + ma_i) = (r - l) / 2;            ma_an = *(ma_r + ma_an) > *(ma_r + ma_i) ? ma_an : ma_i;            ma_li = ma_i;        } else if (ma_i <= ma_mt) {            *(ma_r + ma_i) = ma_mt - ma_i;        } else {            *(ma_r + ma_i) = *(ma_r + ma_mi);        }    }    answer = (char *) malloc(sizeof(char) * (* (ma_r + ma_an) + 1));    *(answer + *(ma_r + ma_an)) = '\0';    l = ma_an - *(ma_r + ma_an);    r = ma_an + *(ma_r + ma_an);    for (i = l; i <= r; i ++) {        if (i % 2 == 1)            *(answer + (j ++)) = _access_char_array(s, i);    }    free(ma_r);    return answer;}int main() {    char* s = "cbbd";    char* a = longestPalindrome(s);    unsigned int i = 0;    printf("len(a) is %d\r\n", strlen(a));    for (i = 0; i < strlen(a); i ++)        printf("%c", *(a + i));    printf("\r\n");    free(a);    return 0;}


Python Solution: github

#coding=utf-8'''    url: leetcode.com/problems/longest-palindromic-substring/    manacher    @author:     zxwtry    @email:      zxwtry@qq.com    @date:       2017年3月26日    @details:    Solution: AC 632ms 41.14%'''class Solution(object):    def accessString(self, s, index):        if index % 2 == 0: return '#'        else: return s[index // 2]            def longestPalindrome(self, s):        """        :type s: str        :rtype: str        """        s_len = 0 if s == None else len(s)        if s_len == 0: return ""        m = [0] * (2 * s_len + 1)        m_last_i, m_mirror_r, m_max_touch_i, m_max_r_index = 0, 0, 0, 0        for i in range(2 * s_len + 1):            if m_max_touch_i >= 2 * s_len: break            m_mirror_r = m[2 * m_last_i - i]            if i >= m_max_touch_i or i + m_mirror_r == m_max_touch_i:                left, right = i, i                while left - 1 > -1 and right + 1 < 2 * s_len + 1 and \                    self.accessString(s, left - 1) == self.accessString(s, right + 1):                    left, right = (left - 1), (right + 1)                m[i] = (right - left) // 2                if m[m_max_r_index] < m[i]:m_max_r_index = i                m_last_i = i                m_max_touch_i = right            elif i + m_mirror_r < m_max_touch_i:                m[i] = m[2 * m_last_i - i]            else:                m[i] = m_max_touch_i - i        i = m_max_r_index // 2 - m[m_max_r_index] // 2        return s[i : i + m[m_max_r_index]]if __name__ == "__main__":    s1="tabatabag"    s = Solution()    print("answer is \"%s\"" % s.longestPalindrome(s1))







0 0
原创粉丝点击