manacher:
class Solution:
'''这里面是利用manacher进一步做从后面添加最少的字串使其成为回文串,leetcode214T是在前面'''
def longestPalindrome(self, s: str) -> str:
# 加进去 '#' 使其奇偶数都行,这个函数简单
def manacherStr(Str) -> List[str]:
res = [0] * (len(Str) * 2 + 1)
idx = 0
for i in range(len(res)):
if not i & 1:
res[i] = '#'
else:
res[i] = Str[idx]
idx += 1
return res
def maxLcpsLength(Str) -> int:
# 上面的生成扩展数组如果是空,会['#']
# if not Str: return Str
# 加上'#' 方便处理奇偶数
charArr = manacherStr(Str)
# pArr是回文半径数组,是对包含#的数组而言
pArr = [0] * len(charArr)
# C回文直径的中心,R回文右边界(回文的右边的那个char的索引,
# 这样R-i正好包括i不包括R,正好是半径)
C, R = -1, -1
'''
maxContainsEnd = -1
'''
# 最大半径对应的中心C
MaxC = 0
Max = float('-inf')
for i in range(len(charArr)):
if R > i:
# 2*C-i是i关于C的对称点索引
pArr[i] = min(pArr[2 * C - i], R - i)
# 当前位置i不在R里面,暴力扩
# 更新回文半径数组
else:
pArr[i] = 1
while i + pArr[i] < len(charArr) and i - pArr[i] > -1:
# 前两种会这一步都扩不动,最后一种会持续扩到不能扩为止
if charArr[i + pArr[i]] == charArr[i - pArr[i]]:
pArr[i] += 1
# 扩不动退出
else:
break
# 扩不动了R移到扩不动的位置
# 更新回文中心和回文右边界
if i + pArr[i] > R:
R = i + pArr[i]
C = i
# 针对此题做的处理
# 更新最大回文半径对应的C,而非最大R
if max(Max, pArr[i]) > Max:
MaxC = i
'''
if R == len(charArr):
maxContainsEnd = pArr[i]
break
'''
Max = max(Max, pArr[i])
'''
res = [0] * (len(Str) - maxContainsEnd + 1)
for i in range(len(res)):
res[len(res) - 1 - i] = charArr[i * 2] + 1
return res
'''
# Max是包括#的最长回文半径(包括中心点)
# 索引加#后的数组的回文半径数组-1就是回文字串的长度
# return Max - 1
# C >> 1 是原数组最后的回文中心
# 如果Max-1是偶数则c/2是下中位数(索引大的那个),若奇数则中间
L = (MaxC >> 1) - (Max - 1 >> 1)
# 空字符Str的Str[0:1]会返回空
return Str[L : L + Max - 1]
return maxLcpsLength(s)
KMP:
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
def getIndexOf(str1, str2) -> int:
# 必须将这个写在前面
if not str2 and not str1:
return 0
# str2为空,那么就默认返回0
if not str2:
return 0
if not str1 or len(str1) < len(str2):
return -1
i1, i2 = 0, 0
nextArray = getNextArray(str2)
while i1 < len(str1) and i2 < len(str2):
# 暴力找相等
if str1[i1] == str2[i2]:
i1 += 1
i2 += 1
# 不等,str1向前走,找到和str2开头一样的第一个char
elif nextArray[i2] == -1:
i1 +=1
# 不等,找到了和str2开头的元素,找最长前后缀匹配的长度,跳到长度索引处
# 继续while下去
else:
i2 = nextArray[i2]
# 返回第一个相等的元素索引,即为两者差值
return i1 - i2 if i2 == len(str2) else -1
def getNextArray(str2) -> List[int]:
length = len(str2)
# 长度为1,默认0号索引的next数组为-1
if length == 1:
return [-1]
nextArray = [0] * length
nextArray[0] = -1
# 当前位置i和跳到的位置cn(最长匹配长度的索引即那一位没有匹配上)
i, cn = 2, 0
while i < length:
# 移动了一步之后,原来的位置和当前最长匹配没有配上的位置的值是否相等
if str2[i-1] == str2[cn]:
# java中nextArray[i++] == ++cn相当于后面三行
nextArray[i] = cn + 1
cn += 1
i += 1
# 移动一步后没有匹配上,则只是cn往前一个最长匹配没配上的位置跳,
# i不变仍是跳的位置和i-1位置比
elif cn > 0:
cn = nextArray[cn]
# 没有配上并且前面没有最长匹配了
# 则没有最长匹配,重新下一个位置
else:
nextArray[i] = 0
i += 1
return nextArray
return getIndexOf(haystack, needle)