Welcome to Subscribe On Youtube
3485. Longest Common Prefix of K Strings After Removal
Description
You are given an array of strings words and an integer k.
For each index i in the range [0, words.length - 1], find the length of the longest common prefix among any k strings (selected at distinct indices) from the remaining array after removing the ith element.
Return an array answer, where answer[i] is the answer for ith element. If removing the ith element leaves the array with fewer than k strings, answer[i] is 0.
Example 1:
Input: words = ["jump","run","run","jump","run"], k = 2
Output: [3,4,4,3,4]
Explanation:
- Removing index 0 (
"jump"):wordsbecomes:["run", "run", "jump", "run"]."run"occurs 3 times. Choosing any two gives the longest common prefix"run"(length 3).
- Removing index 1 (
"run"):wordsbecomes:["jump", "run", "jump", "run"]."jump"occurs twice. Choosing these two gives the longest common prefix"jump"(length 4).
- Removing index 2 (
"run"):wordsbecomes:["jump", "run", "jump", "run"]."jump"occurs twice. Choosing these two gives the longest common prefix"jump"(length 4).
- Removing index 3 (
"jump"):wordsbecomes:["jump", "run", "run", "run"]."run"occurs 3 times. Choosing any two gives the longest common prefix"run"(length 3).
- Removing index 4 ("run"):
wordsbecomes:["jump", "run", "run", "jump"]."jump"occurs twice. Choosing these two gives the longest common prefix"jump"(length 4).
Example 2:
Input: words = ["dog","racer","car"], k = 2
Output: [0,0,0]
Explanation:
- Removing any index results in an answer of 0.
Constraints:
1 <= k <= words.length <= 1051 <= words[i].length <= 104words[i]consists of lowercase English letters.- The sum of
words[i].lengthis smaller than or equal105.
Solutions
Solution 1
-
class Solution { static class TrieNode { int count = 0; int depth = 0; int[] children = new int[26]; TrieNode() { for (int i = 0; i < 26; ++i) children[i] = -1; } } static class SegmentTree { int n; int[] tree; int[] globalCount; SegmentTree(int n, int[] globalCount) { this.n = n; this.globalCount = globalCount; this.tree = new int[4 * (n + 1)]; for (int i = 0; i < tree.length; i++) tree[i] = -1; build(1, 1, n); } void build(int idx, int l, int r) { if (l == r) { tree[idx] = globalCount[l] > 0 ? l : -1; return; } int mid = (l + r) / 2; build(idx * 2, l, mid); build(idx * 2 + 1, mid + 1, r); tree[idx] = Math.max(tree[idx * 2], tree[idx * 2 + 1]); } void update(int idx, int l, int r, int pos, int newVal) { if (l == r) { tree[idx] = newVal > 0 ? l : -1; return; } int mid = (l + r) / 2; if (pos <= mid) { update(idx * 2, l, mid, pos, newVal); } else { update(idx * 2 + 1, mid + 1, r, pos, newVal); } tree[idx] = Math.max(tree[idx * 2], tree[idx * 2 + 1]); } int query() { return tree[1]; } } public int[] longestCommonPrefix(String[] words, int k) { int n = words.length; int[] ans = new int[n]; if (n - 1 < k) return ans; ArrayList<TrieNode> trie = new ArrayList<>(); trie.add(new TrieNode()); for (String word : words) { int cur = 0; for (char c : word.toCharArray()) { int idx = c - 'a'; if (trie.get(cur).children[idx] == -1) { trie.get(cur).children[idx] = trie.size(); TrieNode node = new TrieNode(); node.depth = trie.get(cur).depth + 1; trie.add(node); } cur = trie.get(cur).children[idx]; trie.get(cur).count++; } } int maxDepth = 0; for (int i = 1; i < trie.size(); ++i) { if (trie.get(i).count >= k) { maxDepth = Math.max(maxDepth, trie.get(i).depth); } } int[] globalCount = new int[maxDepth + 1]; for (int i = 1; i < trie.size(); ++i) { TrieNode node = trie.get(i); if (node.count >= k && node.depth <= maxDepth) { globalCount[node.depth]++; } } List<List<Integer>> fragileList = new ArrayList<>(); for (int i = 0; i < n; ++i) { fragileList.add(new ArrayList<>()); } for (int i = 0; i < n; ++i) { int cur = 0; for (char c : words[i].toCharArray()) { int idx = c - 'a'; cur = trie.get(cur).children[idx]; if (trie.get(cur).count == k) { fragileList.get(i).add(trie.get(cur).depth); } } } int segSize = maxDepth; if (segSize >= 1) { SegmentTree segTree = new SegmentTree(segSize, globalCount); for (int i = 0; i < n; ++i) { if (n - 1 < k) { ans[i] = 0; } else { for (int d : fragileList.get(i)) { segTree.update(1, 1, segSize, d, globalCount[d] - 1); } int res = segTree.query(); ans[i] = res == -1 ? 0 : res; for (int d : fragileList.get(i)) { segTree.update(1, 1, segSize, d, globalCount[d]); } } } } return ans; } } -
class Solution { public: struct TrieNode { int count = 0; int depth = 0; int children[26] = {0}; }; class SegmentTree { public: int n; vector<int> tree; vector<int>& globalCount; SegmentTree(int n, vector<int>& globalCount) : n(n) , globalCount(globalCount) { tree.assign(4 * (n + 1), -1); build(1, 1, n); } void build(int idx, int l, int r) { if (l == r) { tree[idx] = globalCount[l] > 0 ? l : -1; return; } int mid = (l + r) / 2; build(idx * 2, l, mid); build(idx * 2 + 1, mid + 1, r); tree[idx] = max(tree[idx * 2], tree[idx * 2 + 1]); } void update(int idx, int l, int r, int pos, int newVal) { if (l == r) { tree[idx] = newVal > 0 ? l : -1; return; } int mid = (l + r) / 2; if (pos <= mid) update(idx * 2, l, mid, pos, newVal); else update(idx * 2 + 1, mid + 1, r, pos, newVal); tree[idx] = max(tree[idx * 2], tree[idx * 2 + 1]); } int query() { return tree[1]; } }; vector<int> longestCommonPrefix(vector<string>& words, int k) { int n = words.size(); vector<int> ans(n, 0); if (n - 1 < k) return ans; vector<TrieNode> trie(1); for (const string& word : words) { int cur = 0; for (char c : word) { int idx = c - 'a'; if (trie[cur].children[idx] == 0) { trie[cur].children[idx] = trie.size(); trie.push_back({0, trie[cur].depth + 1}); } cur = trie[cur].children[idx]; trie[cur].count++; } } int maxDepth = 0; for (int i = 1; i < trie.size(); ++i) { if (trie[i].count >= k) { maxDepth = max(maxDepth, trie[i].depth); } } vector<int> globalCount(maxDepth + 1, 0); for (int i = 1; i < trie.size(); ++i) { if (trie[i].count >= k && trie[i].depth <= maxDepth) { globalCount[trie[i].depth]++; } } vector<vector<int>> fragileList(n); for (int i = 0; i < n; ++i) { int cur = 0; for (char c : words[i]) { int idx = c - 'a'; cur = trie[cur].children[idx]; if (trie[cur].count == k) { fragileList[i].push_back(trie[cur].depth); } } } int segSize = maxDepth; if (segSize >= 1) { SegmentTree segTree(segSize, globalCount); for (int i = 0; i < n; ++i) { if (n - 1 < k) { ans[i] = 0; } else { for (int d : fragileList[i]) { segTree.update(1, 1, segSize, d, globalCount[d] - 1); } int res = segTree.query(); ans[i] = res == -1 ? 0 : res; for (int d : fragileList[i]) { segTree.update(1, 1, segSize, d, globalCount[d]); } } } } return ans; } }; -
class Solution: def longestCommonPrefix(self, words: List[str], k: int) -> List[int]: n = len(words) ans = [0] * n if n - 1 < k: return ans trie = [{'count': 0, 'depth': 0, 'children': [-1] * 26}] for word in words: cur = 0 for c in word: idx = ord(c) - 97 if trie[cur]['children'][idx] == -1: trie[cur]['children'][idx] = len(trie) trie.append( { 'count': 0, 'depth': trie[cur]['depth'] + 1, 'children': [-1] * 26, } ) cur = trie[cur]['children'][idx] trie[cur]['count'] += 1 max_depth = 0 for i in range(1, len(trie)): if trie[i]['count'] >= k: max_depth = max(max_depth, trie[i]['depth']) global_count = [0] * (max_depth + 1) for i in range(1, len(trie)): node = trie[i] if node['count'] >= k and node['depth'] <= max_depth: global_count[node['depth']] += 1 fragile_list = [[] for _ in range(n)] for i, word in enumerate(words): cur = 0 for c in word: idx = ord(c) - 97 cur = trie[cur]['children'][idx] if trie[cur]['count'] == k: fragile_list[i].append(trie[cur]['depth']) seg_size = max_depth if seg_size < 1: return ans tree = [-1] * (4 * (seg_size + 1)) def build(idx: int, l: int, r: int) -> None: if l == r: tree[idx] = l if global_count[l] > 0 else -1 return mid = (l + r) // 2 build(idx * 2, l, mid) build(idx * 2 + 1, mid + 1, r) tree[idx] = max(tree[idx * 2], tree[idx * 2 + 1]) def update(idx: int, l: int, r: int, pos: int, new_val: int) -> None: if l == r: tree[idx] = l if new_val > 0 else -1 return mid = (l + r) // 2 if pos <= mid: update(idx * 2, l, mid, pos, new_val) else: update(idx * 2 + 1, mid + 1, r, pos, new_val) tree[idx] = max(tree[idx * 2], tree[idx * 2 + 1]) build(1, 1, seg_size) for i in range(n): for d in fragile_list[i]: update(1, 1, seg_size, d, global_count[d] - 1) res = tree[1] ans[i] = 0 if res == -1 else res for d in fragile_list[i]: update(1, 1, seg_size, d, global_count[d]) return ans -
type trieNode struct { count int depth int children [26]int } func longestCommonPrefix(words []string, k int) []int { n := len(words) ans := make([]int, n) if n-1 < k { return ans } trie := []trieNode{{}} for i := range trie[0].children { trie[0].children[i] = -1 } for _, word := range words { cur := 0 for _, c := range word { idx := int(c - 'a') if trie[cur].children[idx] == -1 { trie[cur].children[idx] = len(trie) node := trieNode{depth: trie[cur].depth + 1} for j := range node.children { node.children[j] = -1 } trie = append(trie, node) } cur = trie[cur].children[idx] trie[cur].count++ } } maxDepth := 0 for i := 1; i < len(trie); i++ { if trie[i].count >= k { maxDepth = max(maxDepth, trie[i].depth) } } globalCount := make([]int, maxDepth+1) for i := 1; i < len(trie); i++ { if trie[i].count >= k && trie[i].depth <= maxDepth { globalCount[trie[i].depth]++ } } fragileList := make([][]int, n) for i, word := range words { cur := 0 for _, c := range word { idx := int(c - 'a') cur = trie[cur].children[idx] if trie[cur].count == k { fragileList[i] = append(fragileList[i], trie[cur].depth) } } } segSize := maxDepth if segSize < 1 { return ans } tree := make([]int, 4*(segSize+1)) for i := range tree { tree[i] = -1 } var build func(idx, l, r int) build = func(idx, l, r int) { if l == r { if globalCount[l] > 0 { tree[idx] = l } else { tree[idx] = -1 } return } mid := (l + r) / 2 build(idx*2, l, mid) build(idx*2+1, mid+1, r) tree[idx] = max(tree[idx*2], tree[idx*2+1]) } var update func(idx, l, r, pos, newVal int) update = func(idx, l, r, pos, newVal int) { if l == r { if newVal > 0 { tree[idx] = l } else { tree[idx] = -1 } return } mid := (l + r) / 2 if pos <= mid { update(idx*2, l, mid, pos, newVal) } else { update(idx*2+1, mid+1, r, pos, newVal) } tree[idx] = max(tree[idx*2], tree[idx*2+1]) } build(1, 1, segSize) for i := 0; i < n; i++ { for _, d := range fragileList[i] { update(1, 1, segSize, d, globalCount[d]-1) } res := tree[1] if res == -1 { ans[i] = 0 } else { ans[i] = res } for _, d := range fragileList[i] { update(1, 1, segSize, d, globalCount[d]) } } return ans }