目录
758.字符串中加粗单词
给定一个关键词集合 words 和一个字符串 S,将所有 S 中出现的关键词加粗。所有在标签 和 中的字母都会加粗。
返回的字符串需要使用尽可能少的标签,当然标签应形成有效的组合。
例如,给定 words = [“ab”, “bc”] 和 S = “aabcd”,需要返回 “a<b>abc</b>d”。注意返回 “a<b>a<b>b</b>c</b>d” 会使用更多的标签,因此是错误的。
注:
words 长度的范围为 [0, 50]。
words[i] 长度的范围为 [1, 10]。
S 长度的范围为 [0, 500]。
所有 words[i] 和 S 中的字符都为小写字母。
思路
字典树
1.将words建立成一颗字典树用于查找
2.遍历字符串S,创建变量pre用于存储上一段加粗字段的最后一个位置
3.pre初始化为-1,在字符串中找到一个单词,判断这个单词是否在pre之后,若是则重新定义pre且加入"<b>"
4.细节:遍历到pre位置字符串加入"</b>",注意:最后字符串遍历完还需判断pre是否等于字符串长度!!!
5.进一步优化:pre等于字符串长度时,可直接退出(代码自行实现)
struct Node{
Node* a[26];
bool flag;
};
Node *root;
string boldWords(vector<string>& words, string s) {
root = new Node();
for (auto str : words) {
auto p = root;
for (int i = 0; i < str.size(); i++) {
if (p->a[str[i] - 'a'] == NULL) {
p->a[str[i] - 'a'] = new Node();
}
p = p->a[str[i] - 'a'];
}
p->flag = true;
}
//pre表示前面是结束匹配的字符
int pre = -1, index;
string res = "";
for (int i = 0; i < s.size(); i++) {
auto p = root;
index = i;
while (s[index] && p->a[s[index] - 'a']) {
p = p->a[s[index++] - 'a'];
if (p->flag) {
if (i <= pre) {
// i < pre说明匹配到了i之后的了
//pre < index 说明pre这个结束符需要延后
if (pre <= index) pre = index;
} else {
//如果i > pre说明已经是下一个匹配的字符了
res += "<b>";
pre = index;
}
}
}
//表示i前面已经是需要结束符了
if (pre == i) {
res += "</b>";
}
res += s[i];
}
//pre等于末尾时需要补上
if (s.size() == pre) {
res += "</b>";
}
return res;
}
13.罗马数字转整数
题目
思路
罗马数字由 I,V,X,L,C,D,M 构成;
当小值在大值的左边,则减小值,如 IV=5-1=4;
当小值在大值的右边,则加小值,如 VI=5+1=6;
由上可知,右值永远为正,因此最后一位必然为正。
int romanToInt(string s) {
unordered_map<char,int> map = {
{
'I',1} , {
'V', 5} , {
'X',10}, {
'L' , 50}, {
'C',100} , {
'D', 500}, {
'M', 1000}};
int res = 0;
int pre = map[s[0]], now;
for (int i = 1 ; i < s.size(); i++) {
now = map[s[i]];
if (pre < now) {
res -= pre;
} else {
res += pre;
}
pre = now;
}
res += pre;
return res;
}
14.最长公共前序
题目
思路
直接排序后第一个和最后一个进行比较
string longestCommonPrefix(vector<string>& strs) {
if(strs.empty()) return string();
//进行排序
sort(strs.begin(), strs.end());
string st = strs.front(), en = strs.back();
int i, num = min(st.size(), en.size());
for(i =