forked from jeantimex/javascript-problems-and-solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathadd-bold-tag-in-string.js
132 lines (108 loc) · 2.61 KB
/
add-bold-tag-in-string.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
* Add Bold Tag in String
*
* Given a string s and a list of strings dict, you need to add a closed pair of bold tag <b> and </b>
* to wrap the substrings in s that exist in dict. If two such substrings overlap, you need to wrap them
* together by only one pair of closed bold tag. Also, if two substrings wrapped by bold tags are consecutive,
* you need to combine them.
*
* Example 1:
* Input:
* s = "abcxyz123"
* dict = ["abc","123"]
* Output:
* "<b>abc</b>xyz<b>123</b>"
*
* Example 2:
* Input:
* s = "aaabbcc"
* dict = ["aaa","aab","bc"]
* Output:
* "<b>aaabbc</b>c"
*
* Note:
* The given dict won't contain duplicates, and its length won't exceed 100.
* All the strings in input have length in range [1, 1000].
*/
/**
* @param {string} s
* @param {string[]} dict
* @return {string}
*/
const addBoldTag = (s, dict) => {
const trie = new Trie(dict);
let intervals = [];
// Step 1. Get the initial intervals
for (let i = 0; i < s.length; i++) {
const maxLength = trie.search(s.substr(i));
if (maxLength > 0) {
intervals.push({
start: i,
end: i + maxLength - 1,
});
}
}
// Step 2. Merge intervals
intervals = mergeIntervals(intervals);
// Step 3. Add <b></b> tags
const arr = s.split('');
intervals.forEach(({ start, end }) => {
arr[start] = `<b>${arr[start]}`;
arr[end] = `${arr[end]}</b>`;
});
return arr.join('');
};
const mergeIntervals = intervals => {
let i = 0;
for (let j = 0; j < intervals.length; j++) {
const current = intervals[i];
const next = intervals[j];
if (next.start <= current.end + 1) {
current.end = Math.max(current.end, next.end);
} else {
intervals[++i] = next;
}
}
return intervals.slice(0, i + 1);
};
class TrieNode {
constructor() {
this.children = {};
this.length = null;
}
}
class Trie {
constructor(words) {
this.root = new TrieNode();
words.forEach(word => {
this.insert(word);
});
}
insert(word) {
let current = this.root;
for (let i = 0; i < word.length; i++) {
const c = word[i];
if (!(c in current.children)) {
current.children[c] = new TrieNode();
}
current = current.children[c];
}
current.length = word.length;
}
search(s) {
let current = this.root;
let maxLength = 0;
for (let i = 0; i < s.length; i++) {
const c = s[i];
if (!(c in current.children)) {
break;
}
current = current.children[c];
if (current.length !== null) {
maxLength = current.length;
}
}
return maxLength;
}
}
export default addBoldTag;