
2025-12-10:相邻字符串之间的最长公共前缀。用go语言,给定一个字符串数组 words。对每个下标 i(0 到 words.length-1)按下面步骤处理并求得一个整数值:
最终返回一个与原数组同样长度的整数数组 answer,其中 answer[i] 表示删除第 i 个元素后相邻对之间最大的“从头开始相同的连续前缀”的长度。
说明:字符串的前缀指的是从字符串开头连续截取的一段字符。
1 <= words.length <= 100000。
1 <= words[i].length <= 10000。
words[i] 仅由小写英文字母组成。
words[i] 的长度总和不超过 100000。
输入: words = ["jump","run","run","jump","run"]。
输出: [3,0,0,3,3]。
解释:
移除下标 0:
words 变为 ["run", "run", "jump", "run"]
最长的相邻对是 ["run", "run"],其公共前缀为 "run"(长度为 3)
移除下标 1:
words 变为 ["jump", "run", "jump", "run"]
没有相邻对有公共前缀(长度为 0)
移除下标 2:
words 变为 ["jump", "run", "jump", "run"]
没有相邻对有公共前缀(长度为 0)
移除下标 3:
words 变为 ["jump", "run", "run", "run"]
最长的相邻对是 ["run", "run"],其公共前缀为 "run"(长度为 3)
移除下标 4:
words 变为 ["jump", "run", "run", "jump"]
最长的相邻对是 ["run", "run"],其公共前缀为 "run"(长度为 3)
题目来自力扣3598。
首先,代码需要知道原始数组中每一对相邻字符串的最长公共前缀(LCP)长度。这是后续所有计算的基础。
words 数组,从第一个元素到倒数第二个元素,依次计算 words[i] 和 words[i+1] 的LCP长度。计算工作由辅助函数 lcp(s, t string) int 完成。lcp函数的工作方式:该函数比较两个字符串,从第一个字符开始逐个比对,直到遇到不同的字符或其中一个字符串结束。返回匹配的字符数量。mx1) 和次大值 (mx2),并记录最大值所在的位置 i1(即第 i1 和 i1+1 个字符串组成的对拥有最长的LCP)。这一步非常关键,因为删除一个元素是否会影响到全局最大的LCP,取决于是否删除了构成这个最大LCP的那一对字符串中的某一个。i接下来,代码需要模拟删除数组中每一个位置 i 的元素,并计算新数组中相邻对的最大LCP。它通过一个循环,对每个下标 i 进行如下处理:
i 不是数组的头或尾(即 0 < i < n-1)时,删除操作会使得原本不相邻的 words[i-1] 和 words[i+1] 变成新数组中的一对相邻字符串。lcp 函数计算 words[i-1] 和 words[i+1] 的LCP长度,记为 l。这个值代表了删除 words[i] 后新产生的一对相邻字符串的公共前缀长度。i 后,原始数组中的最大LCP (mx1) 能否在新数组中保留,取决于删除操作是否破坏了构成这个最大LCP的相邻对(即位于 i1 和 i1+1 的那一对)。i 既不等于 i1 也不等于 i1+1,那么原始的最大LCP对在新数组中依然完整存在。因此,新数组的最大LCP可能值就是 mx1 和新产生的“跨越”LCP l 之间的较大者。i 正好是 i1 或 i1+1,那么原始的最大LCP对就被破坏了。此时,新数组的最大LCP只能从原始的次大LCP (mx2) 和新产生的“跨越”LCP l 之间取较大值。max(mx1, l) 或 max(mx2, l))存入结果数组 ans 的第 i 个位置。完成对所有下标 i 的遍历后,结果数组 ans 就已经填充完毕,其中 ans[i] 就是删除第 i 个元素后得到的新数组中所有相邻对的最大LCP长度。最后,将这个结果数组输出。
L 的定义:L 代表所有字符串长度的总和(题目中给出 L <= 100000)。L。i(共有 n 个),最多只进行一次额外的LCP计算(即计算“跨越”对的LCP)。同样,这些计算所涉及的字符比较总数也不会超过 L。L 呈线性关系,为 O(L)。ans,其大小与输入数组长度 n 成正比。mx1, mx2, i1)来记录关键信息。lcp 函数等操作只使用了常数级别的临时空间。希望这个分步解释能帮助你清晰地理解整个算法的流程和性能表现。
.
package main
import (
"fmt"
)
func lcp(s, t string)int {
n := min(len(s), len(t))
for i := range n {
if s[i] != t[i] {
return i
}
}
return n
}
func longestCommonPrefix(words []string) []int {
n := len(words)
mx1, mx2, i1 := -1, -1, -2
for i := range n - 1 {
l := lcp(words[i], words[i+1])
if l > mx1 {
mx2 = mx1
mx1, i1 = l, i
} elseif l > mx2 {
mx2 = l
}
}
ans := make([]int, n)
for i := range n {
l := 0
if0 < i && i < n-1 {
l = lcp(words[i-1], words[i+1])
}
if i != i1 && i != i1+1 { // 最大 LCP 没被破坏
ans[i] = max(mx1, l)
} else {
ans[i] = max(mx2, l)
}
}
return ans
}
func main() {
words := []string{"jump", "run", "run", "jump", "run"}
result := longestCommonPrefix(words)
fmt.Println(result)
}

.
# -*-coding:utf-8-*-
from typing import List
def lcp(s: str, t: str) -> int:
"""返回两个字符串的最长公共前缀长度"""
n = min(len(s), len(t))
for i in range(n):
if s[i] != t[i]:
return i
return n
def longestCommonPrefix(words: List[str]) -> List[int]:
n = len(words)
mx1, mx2, i1 = -1, -1, -2
# 找出相邻单词间的最大和次大LCP
for i in range(n - 1):
l = lcp(words[i], words[i + 1])
if l > mx1:
mx2 = mx1
mx1, i1 = l, i
elif l > mx2:
mx2 = l
ans = [0] * n
for i in range(n):
# 计算删除当前单词后的可能LCP
l = 0
if0 < i < n - 1:
l = lcp(words[i - 1], words[i + 1])
# 如果当前索引不在最大LCP对应的相邻索引中,则最大LCP仍可用
if i != i1 and i != i1 + 1:
ans[i] = max(mx1, l)
else:
ans[i] = max(mx2, l)
return ans
if __name__ == "__main__":
words = ["jump", "run", "run", "jump", "run"]
result = longestCommonPrefix(words)
print(result) # 输出: [0, 3, 3, 0, 3]
.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int lcp(conststring& s, conststring& t) {
int n = min(s.length(), t.length());
for (int i = 0; i < n; i++) {
if (s[i] != t[i]) {
return i;
}
}
return n;
}
vector<int> longestCommonPrefix(const vector<string>& words) {
int n = words.size();
int mx1 = -1, mx2 = -1, i1 = -2;
// 找出相邻单词间的最大和次大LCP
for (int i = 0; i < n - 1; i++) {
int l = lcp(words[i], words[i + 1]);
if (l > mx1) {
mx2 = mx1;
mx1 = l;
i1 = i;
} elseif (l > mx2) {
mx2 = l;
}
}
vector<int> ans(n, 0);
for (int i = 0; i < n; i++) {
int l = 0;
if (0 < i && i < n - 1) {
l = lcp(words[i - 1], words[i + 1]);
}
if (i != i1 && i != i1 + 1) {
ans[i] = max(mx1, l);
} else {
ans[i] = max(mx2, l);
}
}
return ans;
}
int main() {
vector<string> words = {"jump", "run", "run", "jump", "run"};
vector<int> result = longestCommonPrefix(words);
cout << "[";
for (size_t i = 0; i < result.size(); i++) {
cout << result[i];
if (i < result.size() - 1) {
cout << ", ";
}
}
cout << "]" << endl;
return0;
}

我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。