class Solution {
public:
string boldWords(vector<string>& words, string s) {
string ans;
vector<pair<int, int>> intervals;
vector<pair<int, int>> merged;
for (const string& word : words) {
const int n = word.length();
for (int i = 0; i + n <= s.length(); ++i)
if (s.substr(i, n) == word)
intervals.emplace_back(i, i + n);
}
if (intervals.empty())
return s;
ranges::sort(intervals);
for (const pair<int, int>& interval : intervals)
if (merged.empty() || merged.back().second < interval.first)
merged.push_back(interval);
else
merged.back().second = max(merged.back().second, interval.second);
int prevEnd = 0;
for (const auto& [startIndex, endIndex] : merged) {
ans += s.substr(prevEnd, startIndex - prevEnd);
ans += "<b>" + s.substr(startIndex, endIndex - startIndex) + "</b>";
prevEnd = endIndex;
}
if (!merged.empty())
ans += s.substr(merged.back().second);
return ans;
}
};