【无标题】

马拉车算法

算法的思想是通过在字符串的每个字符之间插入特殊字符(例如"#"),将问题转化为奇数长度的回文串的问题。这样可以统一处理奇数长度和偶数长度的回文串。

时间复杂度:该算法的时间复杂度为O(n),其中n是字符串的长度。马拉车算法只需遍历一次字符串,并且每次遍历都是常数时间操作。

空间复杂度:该算法的空间复杂度为O(n),其中n是字符串的长度。需要额外的空间存储新字符串和p数组。

算法的步骤如下:

  1. 初始化一个新字符串,将原始字符串进行预处理,插入特殊字符。
  2. 创建一个数组p,用于存储每个字符作为回文中心时的回文半径。
  3. 维护两个变量center和rightBoundary,分别表示当前最长回文子串的中心和右边界。
  4. 遍历新字符串的每个字符,根据不同情况计算回文半径:
    • 如果当前字符在rightBoundary的左边,可以利用对称点的回文半径计算当前字符的回文半径。
    • 如果当前字符在rightBoundary的右边或恰好处于rightBoundary上,则需要从中心向两边扩散,检查回文长度。
  5. 更新最长回文子串的中心和右边界。
  6. 根据p数组和原字符串s,返回最长回文子串。

func main(){
	var s string
	s="abcabacdab"
	ansStr:=longestPalindrome(s)
	fmt.Println(ansStr)
}
//5.最长回文子串
func longestPalindrome(s string) string {
	// 将字符串转换为新的字符串,用于支持奇偶长度的回文串
	ns := initNewString(s)
	// 存储每个字符作为回文中心时的回文半径
	p := make([]int, len(ns))

	// center:当前最长回文子串的中心,rightBoundary:当前最长回文子串的右边界
	center, rightBoundary := 0, 0

	for i := range ns {
		// i_mirror:i关于center的对称点
		i_mirror := center*2-i

		// 当 i 在 rightBoundary 的左边,可以利用i_mirror的回文半径计算i的回文半径
		if i<rightBoundary {
			p[i] = min(p[i_mirror], rightBoundary-i)

			// 只有当 i_mirror 的回文半径刚好达到 center 回文的左边界时,
			// 才需要检查右边界外面的字符是否能够形成新的回文
			if p[i_mirror] != rightBoundary-i {
				continue
			}
		}

		// 从中心向两边扩散,检查回文长度
		for r := p[i]; i-r >= 0 && i+r <= len(ns)-1; r++ {
			if ns[i-r] != ns[i+r] {
				break
			}

			p[i] = r
		}

		// 更新最长回文子串的中心和右边界
		if i+p[i] > rightBoundary {
			center = i
			rightBoundary = i+p[i]
		}
	}

	// 根据p数组和原字符串s返回最长回文子串
	return longest(s, p)
}

// 根据p数组和原字符串s返回最长回文子串
func longest(s string, p []int) string {
	center, maxRadius := 0, 0
	for i, r := range p {
		if r > maxRadius {
			center = i
			maxRadius = r
		}
	}

	start := (center-maxRadius)/2

	return s[start:start+maxRadius]
}

// 初始化新字符串
func initNewString(s string) string {
	bytes := make([]byte, len(s)*2+3)

	bytes[0] = '^'
	bytes[len(bytes)-1] = '$'
	for i, c := range s {
		bytes[i*2+1] = '#'
		bytes[i*2+2] = byte(c)
		bytes[i*2+3] = '#'
	}

	return string(bytes)
}

// 返回a和b中的最小值
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值