题解 | #最长回文子串#

最长回文子串

https://www.nowcoder.com/practice/b4525d1d84934cf280439aeecc36f4af

#include <utility>
#include <vector>
class Solution {
  public:
    string preprocess(const string& s) { //预处理字符串
        string result = "^#"; //‘^’为开始标识符
        for (char c : s) {
            result += c;
            result += "#"; //间隔插入‘#’号,将奇数和偶数长度的回文串统一为奇数长度
        }
        result += "$"; //‘$’为结束标识符,开始和结束标识符用于防止访问越界
        return result;
    }
    int getLongestPalindrome(string A) {
        A = preprocess(A); //预处理字符串
        int n = A.size();
        vector<int> P(n, 1); //P[i]表示以A[i]为中心的回文串的半径(含中心)
        int id = 0, mx = 0, maxLen = 0; //id表示已知右边界最右的回文串的中心位置,mx表示该回文串的右边界(即目前的最右边界),maxlen用于记录处理后字符串的最长回文串的长度
        for (int i = 1; i < n - 1; ++i) {
            int i_mirror = 2 * id - i; //i_mirror表示i关于id的对称点(id-(i-id))
            if (mx > i) P[i] = min(mx - i, P[i_mirror]); // 点睛之笔!根据回文串的对称性,已知右边界最右的回文串的左右两部分内的对称点应具有在该回文串直径范围内相同的回文半径,若超出该回文串范围,则只截取到右边界。
            while (A[i + P[i]] == A[i - P[i]]) { //中心扩散法确定i位置的回文半径,即使mx>i也要经过这一步的检查
                P[i]++;
            }
            if (P[i] + i > mx) { //若新的回文串右边界超出mx,则更新中心点id和最右边界mx
                id = i;
                mx = P[i] + i;
            }

            maxLen = P[i] > maxLen ? P[i] : maxLen; //更新最长长度
        }
        return maxLen - 1;  //(x+x+1)/2 +0.5=maxlen => x=maxlen-1,x是要求的原始最大长度,+0.5是因为插入‘#’后必为奇数长度,求包含中心的半径长度要在除2后加0.5
    }
};

全部评论

相关推荐

不愿透露姓名的神秘牛友
2024-12-30 18:02
程序员牛肉:1.可以标记一下自己的学校是985,有一些hr可能没想到你这个院校是985的。 2.简历所呈现出来的能力还是有点差的,苍穹外卖+黑马点评。这在java技术域里面也就是刚学三四个月的样子,大厂现在招人少,小厂又更加希望你能直接过来干活。就你简历上呈现出来的能力,确实是有点难找,肉眼可见的不懂技术。 第一个项目中:简单的使用redis也算是亮点嘛?使用jwt,threadlocal也算是亮点?你不就是调了几个包嘛?Nginx作为服务器也能写出来,这不是前端的活嘛? 第二个项目中:分布式锁+mq消息队列+Lua队列。真没啥好问的。属于面试官看一眼就阳痿的简历,没有任何想提问的欲望。 我给你建议是好好的挖一挖这个项目吧,其实苍穹外卖和黑马点评这两个项目很不错了,只不过是太烂大街了导致面试官没啥问的兴趣,所以不太推荐写简历上。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务