📅  最后修改于: 2023-12-03 15:04:19.691000             🧑  作者: Mango
问题描述:给定一个字符串,最少修改几个字符,才可以把该字符串的左右旋转后得到的字符串变成相同的。
这个问题可以转化为:找到字符串中第一个循环同构子串,并计算左右两边各要修改多少个字符,使得两端变成相同的循环同构子串。
具体的算法如下:
代码实现如下:
def kmp_fail(p: str) -> List[int]:
m = len(p)
fail = [0] * (m + 1)
i, j = 0, -1
fail[0] = -1
while i < m:
while j >= 0 and p[i] != p[j]:
j = fail[j]
i, j = i + 1, j + 1
fail[i] = j
return fail
def kmp(p: str, t: str) -> Optional[int]:
n, m = len(t), len(p)
fail = kmp_fail(p)
i, j = 0, 0
while i < n:
while j >= 0 and t[i] != p[j]:
j = fail[j]
i, j = i + 1, j + 1
if j == m:
return i - m
return None
def rotate_minimal_change(s: str) -> int:
n = len(s)
kmp_len = kmp(s, s[::-1])
if kmp_len is None: # 如果字符串不具有左右旋转同构的特性,则必须修改所有字符
return n
prefix_len = n - kmp_len
suffix_len = kmp_len
return min(prefix_len, suffix_len)
s = "acba"
print(rotate_minimal_change(s)) # 1
KMP算法的时间复杂度是$O(n+m)$,其中$n$是文本串的长度,$m$是模式串的长度。由于此程序先反转字符串,所以它的运行时间是$O(n)$。因此,此程序的总运行时间是$O(n)$。