最少前缀操作问题解析
问题描述
给定两个字符串 S 和 T,目标是通过一系列操作将 S 转变为 T 的前缀。操作包括两种类型:
- 修改操作:可以更改 S 中的任意字符,使其与 T 中相应位置的字符相匹配。
- 删除操作:可以移除 S 末尾的字符,直到其长度不超过 T。
我们的目标是计算出将 S 转换为 T 的前缀所需的最少操作次数。
思路分析
1. 前缀匹配的理解
前缀是指一个字符串的起始部分。例如,"abc" 的前缀包括:""、"a"、"ab" 和 "abc"。任务是将 S 转变为 T 的前缀,即保留 S 的一部分,使其与 T 相匹配,并处理多余的部分。
2. 确定最大公共前缀
首先,我们需要确定 S 和 T 的最大公共前缀,即两者从左到右相同的部分。不属于这个公共前缀的部分需要通过操作来处理。
3. 操作细节
- 修改操作:当 S 和 T 的最大公共前缀不一致时,需要更改 S 中的某些字符以匹配 T。
- 删除操作:如果 S 的长度超过 T,需要移除 S 末尾的字符,以使其成为 T 的前缀。
4. 优化策略
为了找到最少的操作次数,我们可以分两步计算:
- 计算最大公共前缀的长度。
- 对于超出公共前缀的部分,分别计算修改和删除操作的次数。
解题步骤
- 计算最大公共前缀长度:从 S 和 T 的开头开始比较,直到遇到第一个不同的字符或任一字符串结束。
- 修改操作:对于不匹配的字符,每次操作可以更改 S 中的字符,以匹配 T 中的字符。
- 删除操作:如果 S 的长度超过 T,则需要移除 S 中的多余字符。
- 返回操作次数:将修改和删除操作的次数相加,得到总的最少操作次数。
代码实现
def min_operations(S: str, T: str) -> int:
# 计算 S 和 T 的最大公共前缀长度
common_prefix_len = 0
while common_prefix_len < len(S) and common_prefix_len < len(T) and S[common_prefix_len] == T[common_prefix_len]:
common_prefix_len += 1
# 计算 S 中与 T 不匹配的字符数量
modify_count = sum(1 for i in range(common_prefix_len, len(T)) if S[i] != T[i])
# 计算需要删除的 S 的末尾字符数量
delete_count = len(S) - common_prefix_len
# 返回总的操作次数
return modify_count + delete_count
# 测试用例
if __name__ == '__main__':
print(min_operations("aba", "abb")) # 输出:1
print(min_operations("abcd", "efg")) # 输出:4
print(min_operations("xyz", "xy")) # 输出:1
print(min_operations("hello", "helloworld")) # 输出:0
print(min_operations("same", "same")) # 输出:0
复杂度分析
- 时间复杂度:O(min(len(S), len(T))),因为我们需要遍历 S 和 T 的前缀部分进行比较。
- 空间复杂度:O(1),因为我们只使用了常数级别的额外空间。