LeetCode Day.03 Longest Palindromic Substring

本文探讨了多种算法解决寻找字符串中最长回文子串的问题,包括O(n^3)、O(n^2)和高效的O(n)Manacher's Algorithm,并分享了优化技巧避免最坏情况。

这道题花了好长时间

题目描述

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.

Example 2:

Input: “cbbd”
Output: “bb”

算法分析

  1. 为了测试系统,先写一个O(n3)的算法,对于任意的起点i和终点j,判断s[i,j]是否为回文串。GG
    在这里插入图片描述
  2. 为了提升算法,优化到O(n2).对于任意的中心位置i,向两端扩展k,判断s[i-k]==s[i+k]。
    在这里插入图片描述
  3. 后来发现了一个复杂度为O(n)的Manacher’s Algorithm
    在这里插入图片描述
    具体算法内容讲解如果看的人多就更(^ ^)估计是没机会了
class Solution {
public:
    	string longestPalindrome(string s) {
		if(s.length()==0)
            return "";
		string tmp = "#";
		int length = s.length();
		for (int i = 0;i < length;++i)
		{
			tmp += s[i];
			tmp += '#';
		}

		int len = 2 * length + 1;
		int *p = new int[len];
		for (int i = 0;i < len;++i)
			p[i] = 0;

		int start, end;

		updateP(tmp,p, len,&start,&end);


		int ss = start / 2;
		length = (end - start+1)/2 ;
		return s.substr(ss, length);
	}

	void updateP(string s,int *p, int len,int *start,int *end)
	{
		int mx=0, po=0, ans = 0;
		for (int i = 1;i < len-1;++i)
		{
			p[i]=mx>i?Min(mx-i,p[2*po-i]):1;

			while (s[i - p[i]] - s[i + p[i]] == 0) {
				p[i]++;
				if (i - p[i] < 0 || i + p[i] >= len)
					break;
			}

			if (p[i] + i > mx) {
				mx = p[i] + i;
				po = i;
			}

			if (ans < p[i]) {
				ans = p[i];
				*start = i - p[i]+1;
				*end = i + p[i]-1;
			}
		}
	}

	int Min(int a, int b)
	{
		return a < b ? a : b;
	}

};

  1. 由上一篇学到的绝学,这一次学以致用,在算法3的基础上加快了cin
    在这里插入图片描述
    在这里插入图片描述
static int fastiofunc() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    return 0;
}

static int fastio = fastiofunc();
  1. 瞄了一眼最好的算法,居然是用了trick的O(n2)算法,撞出来的最好结果,社会社会
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
class Solution {
public:
    	string longestPalindrome(string s) {
        if (s.empty()) return "";
        if (s.size() == 1) return s;
        int min_start = 0, max_len = 1;
        for (int i = 0; i < s.size();) {
          //if (s.size() - i <= max_len / 2) break;
          int j = i, k = i;
          while (k < s.size()-1 && s[k+1] == s[k]) ++k; // Skip duplicate characters.
          i = k+1;
          while (k < s.size()-1 && j > 0 && s[k + 1] == s[j - 1]) { ++k; --j; } // Expand.
          int new_len = k - j + 1;
          if (new_len > max_len) { min_start = j; max_len = new_len; }
        }
        return s.substr(min_start, max_len);
    }

};

要说为什么的话,因为这两行

while (k < s.size()-1 && s[k+1] == s[k]) ++k; // Skip duplicate characters.
          i = k+1;

onjudge在构造让O(n2)达到最坏复杂度的情况,基于这个算法考虑,最坏情况大多数是很长的重复相同字符的字符串,比如“aaaaaaaaaaaaaa”,这样只要处理这种情况,加入上面这两句,就能有效避免O(n2)最坏情况出现。不得不说,到底是瞎猫碰到了死耗子,还是大佬过于社会呢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值