1- // Time: O(s * d * l), l is the average string length
2- // Space: O(s )
1+ // Time: O(n * d * l), l is the average string length
2+ // Space: O(n )
33
4+ // 16ms
45class Solution {
56public:
67 string addBoldTag (string s, vector<string>& dict) {
@@ -24,3 +25,71 @@ class Solution {
2425 return result;
2526 }
2627};
28+
29+ // Time: O(n * l), l is the average string length
30+ // Space: O(t) , t is the size of trie
31+ // 142ms
32+ class Solution2 {
33+ public:
34+ string addBoldTag (string s, vector<string>& dict) {
35+ TrieNode trie;
36+ for (const auto & word : dict) {
37+ trie.Insert (word);
38+ }
39+
40+ vector<bool > lookup (s.length ());
41+ for (int i = 0 ; i < s.length (); ++i) {
42+ auto curr = ≜
43+ int k = i - 1 ;
44+ for (int j = i; j < s.length (); ++j) {
45+ if (!curr->leaves .count (s[j])) {
46+ break ;
47+ }
48+ curr = curr->leaves [s[j]];
49+ if (curr->isString ) {
50+ k = j;
51+ }
52+ }
53+ fill (lookup.begin () + i, lookup.begin () + k + 1 , true );
54+ }
55+
56+ string result;
57+ for (int i = 0 ; i < s.length (); ++i) {
58+ if (lookup[i] && (i == 0 || !lookup[i - 1 ])) {
59+ result += " <b>" ;
60+ }
61+ result.push_back (s[i]);
62+ if (lookup[i] && (i == (s.length () - 1 ) || !lookup[i + 1 ])) {
63+ result += " </b>" ;
64+ }
65+ }
66+ return result;
67+ }
68+
69+ private:
70+ struct TrieNode {
71+ bool isString;
72+ unordered_map<char , TrieNode *> leaves;
73+
74+ TrieNode () : isString{false } {}
75+
76+ void Insert (const string& s) {
77+ auto * p = this ;
78+ for (const auto & c : s) {
79+ if (!p->leaves [c]) {
80+ p->leaves [c] = new TrieNode;
81+ }
82+ p = p->leaves [c];
83+ }
84+ p->isString = true ;
85+ }
86+
87+ ~TrieNode () {
88+ for (auto & kvp : leaves) {
89+ if (kvp.second ) {
90+ delete kvp.second ;
91+ }
92+ }
93+ }
94+ };
95+ };
0 commit comments