diff --git a/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/README.md b/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/README.md index e7fc56d1e6e20..1cc9dda7c9806 100644 --- a/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/README.md +++ b/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/README.md @@ -114,13 +114,248 @@ tags: #### Java ```java - +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 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> 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; + } +} ``` #### C++ ```cpp - +class Solution { +public: + struct TrieNode { + int count = 0; + int depth = 0; + int children[26] = {0}; + }; + + class SegmentTree { + public: + int n; + vector tree; + vector& globalCount; + SegmentTree(int n, vector& 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 longestCommonPrefix(vector& words, int k) { + int n = words.size(); + vector ans(n, 0); + if (n - 1 < k) return ans; + vector 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 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> 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; + } +}; ``` #### Go diff --git a/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/README_EN.md b/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/README_EN.md index 1669f53620258..e2f26d7aba3ae 100644 --- a/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/README_EN.md +++ b/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/README_EN.md @@ -108,13 +108,248 @@ tags: #### Java ```java - +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 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> 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; + } +} ``` #### C++ ```cpp - +class Solution { +public: + struct TrieNode { + int count = 0; + int depth = 0; + int children[26] = {0}; + }; + + class SegmentTree { + public: + int n; + vector tree; + vector& globalCount; + SegmentTree(int n, vector& 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 longestCommonPrefix(vector& words, int k) { + int n = words.size(); + vector ans(n, 0); + if (n - 1 < k) return ans; + vector 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 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> 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; + } +}; ``` #### Go diff --git a/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/Solution.cpp b/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/Solution.cpp new file mode 100644 index 0000000000000..fa4ada62e21a0 --- /dev/null +++ b/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/Solution.cpp @@ -0,0 +1,107 @@ +class Solution { +public: + struct TrieNode { + int count = 0; + int depth = 0; + int children[26] = {0}; + }; + + class SegmentTree { + public: + int n; + vector tree; + vector& globalCount; + SegmentTree(int n, vector& 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 longestCommonPrefix(vector& words, int k) { + int n = words.size(); + vector ans(n, 0); + if (n - 1 < k) return ans; + vector 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 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> 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; + } +}; \ No newline at end of file diff --git a/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/Solution.java b/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/Solution.java new file mode 100644 index 0000000000000..6b158681eca70 --- /dev/null +++ b/solution/3400-3499/3485.Longest Common Prefix of K Strings After Removal/Solution.java @@ -0,0 +1,130 @@ +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 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> 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; + } +} \ No newline at end of file