Skip to content

Commit 36c4833

Browse files
authored
Create longest-common-prefix-of-k-strings-after-removal.cpp
1 parent b95751c commit 36c4833

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Time: O(l * nlogn)
2+
// Space: O(n)
3+
4+
// sort, sliding window, prefix sum
5+
class Solution {
6+
public:
7+
vector<int> longestCommonPrefix(vector<string> &words, int k) {
8+
vector<int> idxs(size(words));
9+
iota(begin(idxs), end(idxs), 0);
10+
sort(begin(idxs), end(idxs), [&](const auto& i, const auto& j) {
11+
return words[i] < words[j];
12+
});
13+
14+
const auto& longest_common_prefix = [&](int k) {
15+
vector<int> lcp(size(words));
16+
for (int i = 0; i + (k - 1) < size(words); ++i) {
17+
const auto& left = words[idxs[i]];
18+
const auto& right = words[idxs[i + (k - 1)]];
19+
int j = 0;
20+
for (; j < min(size(left), size(right)); ++j) {
21+
if(left[j] != right[j]) {
22+
break;
23+
}
24+
}
25+
lcp[i] = j;
26+
}
27+
return lcp;
28+
};
29+
30+
vector<int> lcp = longest_common_prefix(k);
31+
vector<int> prefix(size(words));
32+
prefix[0] = lcp[0];
33+
for(int i = 0; i + 1 < size(prefix); ++i) {
34+
prefix[i + 1] = max(prefix[i], lcp[i + 1]);
35+
}
36+
vector<int> suffix(size(words));
37+
suffix[size(words) - 1] = lcp[size(words) - 1];
38+
for (int i = size(suffix) - 2; i >= 0; --i) {
39+
suffix[i] = max(suffix[i + 1], lcp[i]);
40+
}
41+
vector<int> result(size(words));
42+
const int mx = ranges::max(longest_common_prefix(k + 1));
43+
for (int i = 0; i < size(words); i++) {
44+
const int idx = idxs[i];
45+
const int mx1 = i - k >= 0 ? prefix[i - k] : 0;
46+
const int mx2 = i + 1 < size(words) ? suffix[i + 1] : 0;
47+
result[idx] = max({mx, mx1, mx2});
48+
}
49+
return result;
50+
}
51+
};
52+
53+
// Time: O(n * l)
54+
// Space: O(t)
55+
// trie
56+
class Solution2 {
57+
private:
58+
class Trie {
59+
public:
60+
Trie() {
61+
new_node();
62+
}
63+
64+
void update(const string& w, int d, int k) {
65+
int curr = 0;
66+
vector<int> path(size(w) + 1, -1);
67+
path[0] = 0;
68+
for (int i = 0; i < size(w); ++i) {
69+
const int x = w[i] - 'a';
70+
if (nodes_[curr][x] == -1) {
71+
nodes_[curr][x] = new_node();
72+
}
73+
path[i + 1] = curr = nodes_[curr][x];
74+
}
75+
for (int i = size(path) - 1; i >= 0; --i) {
76+
const int curr = path[i];
77+
cnts_[curr] += d;
78+
mxs_[curr] = cnts_[curr] >= k ? i : 0;
79+
for (int x = 0; x < 26; ++x) {
80+
if (nodes_[curr][x] != -1) {
81+
mxs_[curr] = max(mxs_[curr], mxs_[nodes_[curr][x]]);
82+
}
83+
}
84+
}
85+
}
86+
87+
int query() {
88+
return mxs_[0];
89+
}
90+
91+
private:
92+
int new_node() {
93+
nodes_.emplace_back(26, -1);
94+
cnts_.emplace_back(0);
95+
mxs_.emplace_back(0);
96+
return size(nodes_) - 1;
97+
}
98+
99+
vector<vector<int>> nodes_;
100+
vector<int> cnts_, mxs_;
101+
};
102+
103+
public:
104+
vector<int> longestCommonPrefix(vector<string>& words, int k) {
105+
Trie trie;
106+
for (const auto& w : words) {
107+
trie.update(w, +1, k);
108+
}
109+
vector<int> result(size(words));
110+
for (int i = 0; i < size(words); ++i) {
111+
trie.update(words[i], -1, k);
112+
result[i] = trie.query();
113+
trie.update(words[i], +1, k);
114+
}
115+
return result;
116+
}
117+
};

0 commit comments

Comments
 (0)