【无标题】

马拉车算法

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

时间复杂度:该算法的时间复杂度为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= 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
}

你可能感兴趣的:(数学建模,java,开发语言)