zoukankan      html  css  js  c++  java
  • LeetCode Longest Palindromic Substring

    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.

    class Solution {
    private:
        const char sep_char     = '1';
    public:
        string longestPalindrome(string s) {
            int max_len = 0;
            int len = s.length();
            if (len <= 1) return s;
            
            string str;
            str.push_back(sep_char);
            for (int i=0; i<len; i++) {
                str.push_back(s[i]);
                str.push_back(sep_char);
            }
            int nlen = 2 * len + 1;
            vector<int> P(nlen, 0);
            
            int last_i = 0;
            int last_r = 0;
            
            int maxv = -1;
            int maxi = -1;
    
            for (int i=0; i<nlen; i++) {
                int p = i, q = i;
                if (i < last_r) {
                    int j = 2 * last_i - i;     // (i + j) / 2 = last_i
                    int slen = min(P[j], last_r - i);
                    p-= slen;
                    q+= slen;
                }
                
                while(p >= 0 && q < nlen && str[p] == str[q]) p--, q++;
                if (q > last_r) {
                    last_r = q;
                    last_i = i;
                }
    
                P[i] = q - i;
                
                if (P[i] > maxv) {
                    maxv = P[i];
                    maxi = i;
                }
            }
            return s.substr((maxi + 1 - P[maxi]) / 2, P[maxi] - 1);
        }
    };

    Manacher算法实现,不能懈怠

    第二轮:

    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.

    以前做得真是没什么印象了,因为题目中规定了不超过1000数量不大,先写个简单的:

    // 13:37
    class Solution {
    public:
        string longestPalindrome(string s) {
            int n = s.size();
            if (n <= 1) {
                return s;
            }
            const char* str = s.c_str();
            
            int maxlen = 1;
            int ts = 0, te = 0;
            int ms = 0, me = 0;
            for (int i=0; i<n; i++) {
                int tlen = countPal(str, i, n, ts, te);
                if (tlen > maxlen) {
                    maxlen = tlen;
                    ms = ts;
                    me = te;
                }
            }
            return s.substr(ms, me-ms+1);
        }
        
        int countPal(const char* str, int mid, int n, int& s, int& e) {
            if (mid < 0 || mid >= n) return 0;
            int maxlen = 1;
            int l = mid - 1;
            int r = mid + 1;
            s = l;
            e = r;
            while (l >= 0 && r < n && str[l] == str[r]) {
                if (r - l + 1 > maxlen) {
                    maxlen = r-l+1;
                    s = l;
                    e = r;
                }
                l--, r++;
            }
            l = mid;
            r = mid + 1;
            while (l >= 0 && r < n && str[l] == str[r]) {
                if (r - l + 1 > maxlen) {
                    maxlen = r - l + 1;
                    s = l;
                    e = r;
                }
                l--, r++;
            }
            return maxlen;
        }
    };

     

    i为当前遍历到的字符,如果它在一个已知的回文串内(即last_r>i,last_r为已知的回文串中右端最靠右的索引+1),那么在这个回文串内存在一个和i关于该回文串中心last_i的一个对称位置j(设已经由先前步骤记录为last_i,它和last_r是同一个已知回文串的参数)。如果在j位置上存在一定长度的回文串,那么在i上也回同样的存在。但它们的长度很可能是不一样的,有下面几种情况

    1. 如图中的情况A段回文串已经超出了以last_i为中心的回文范围,所以我们可以直接判断是回文的部分只有B段,剩下的部分还是需要一一比较。

    2. 如果图中的A段完全在已知回文串内,则以i为中心的回文串至少和以j为中心的回文长度一致,外延部分需要逐一比较

    int slen = min(P[j], last_r - i);
    P为存储回文中心到回文外延的长度数组


    改写一下代码:
    class Solution {
    public:
        string longestPalindrome(string s) {
            int len = s.size();
            
            string ms = "$";
            for (int i=0; i<len; i++) {
                ms.push_back(s[i]);
                ms.push_back('$');
            }
            
            int mlen = ms.size();
            vector<int> dp(mlen, 1);
            
            int far = 0;
            int lcenter = 0;
            int maxlen = 0;
            int center = 0;
            
            for (int i=0; i<mlen; i++) {
                int p = i, q = i;
                if (i < far) {
                    int mirror = 2 * lcenter - i;
                    int step = min(far - i, dp[mirror]);
                    p-=step;
                    q+=step;
                }
                while (p >= 0 && q < mlen && ms[p] == ms[q]) {
                    p--, q++;
                }
                if (q > far) {
                    far = q;
                    lcenter = i;
                }
                dp[i] = q - i;
                if (dp[i] > maxlen) {
                    maxlen = dp[i];
                    center = i;
                }
            }
            
            int slen = (maxlen * 2 - 1) / 2;
            int start = (center - maxlen + 1) / 2;
            return s.substr(start, slen);
        }
    };
  • 相关阅读:
    【slenium专题】Webdriver同步设置
    【Selenium专题】WebDriver启动firefox浏览器
    【Selenium专题】WebDriver启动Chrome浏览器(二)
    【Selenium专题】WebDriver启动Chrome浏览器(一)
    Jenkins邮件设置
    Jenkins安装笔记
    for循环输出i为同一值的问题,SetTimeOut
    const、let、var的区别
    浏览器title失去焦点时改变title
    clone对象或数组
  • 原文地址:https://www.cnblogs.com/lailailai/p/3965529.html
Copyright © 2011-2022 走看看