难度中等169
哦,不!你不小心把一个长篇文章中的空格、标点都删掉了,并且大写也弄成了小写。像句子"I reset the computer. It still didn’t boot!"
已经变成了"iresetthecomputeritstilldidntboot"
。在处理标点符号和大小写之前,你得先把它断成词语。当然了,你有一本厚厚的词典dictionary
,不过,有些词没在词典里。假设文章用sentence
表示,设计一个算法,把文章断开,要求未识别的字符最少,返回未识别的字符数。
注意:本题相对原题稍作改动,只需返回未识别的字符数
示例:
输入:
dictionary = ["looked","just","like","her","brother"]
sentence = "jesslookedjustliketimherbrother"
输出: 7
解释: 断句后为"jess looked just like tim her brother",共7个未识别字符。
提示:
0 <= len(sentence) <= 1000
dictionary
中总字符数不超过 150000。- 你可以认为
dictionary
和sentence
中只包含小写字母。
题解:采用动态规划,创建一个数组 dp[] 用来记录结果。句子从前往后看,其中 dp[0]=0 表示句子是空字符串时没有未识别的字符,dp[i] 表示句子前 i 个字符中最少的未识别字符数。
对于前 i 个字符,即句子字符串的 [0,i),它可能是由最前面的 [0,j)子字符串加上一个字典匹配的单词得到,也就是 dp[i]=dp[j], j<i;也可能没找到字典中的单词,可以用它前 i-1 个字符的结果加上一个没有匹配到的第 i 个字符,即 dp[i]=dp[i-1]+1,每次更新最小的dp[i]。
为了更好的查找是否存在满足的字典,采用字典树结构优化,采用从末尾开始查找匹配到的字典,通过具体详解见:https://leetcode-cn.com/problems/re-space-lcci/solution/hui-fu-kong-ge-by-leetcode-solution/
class Trie {
public:
Trie* next[26] = { nullptr }; //存储可能的下一个字符(小写字母共26位)
bool isEnd;
Trie() { isEnd = 0; }
// 从末尾建立树
void insert(string s) {
Trie* cur = this;
for (int i = s.length() - 1; i >= 0; --i) {
int t = s[i] - 'a';
if (cur->next[t] == nullptr) {
cur->next[t] = new Trie();
}
cur = cur->next[t];
}
cur->isEnd = 1;
}
};
class Solution {
public:
int respace(vector<string>& dictionary, string sentence) {
Trie* head = new Trie();
for (auto s : dictionary)
head->insert(s);
vector<int>dp(sentence.size() + 1,INT32_MAX);
dp[0] = 0;
for (int i = 1; i <dp.size(); ++i) {
Trie* cur = head;
dp[i] = dp[i - 1] + 1;
for (int j = i - 1; j >= 0; j--) {
int num = sentence[j] - 'a';
if (cur->next[num] == nullptr) {
break;
}
else if (cur->next[num]->isEnd) {
dp[i] = min(dp[i], dp[j]);
}
// if(dp[i] == 0)
// break;
cur = cur->next[num];
}
}
return dp[sentence.size()];
}
};
难度中等21
给定一个较长字符串big
和一个包含较短字符串的数组smalls
,设计一个方法,根据smalls
中的每一个较短字符串,对big
进行搜索。输出smalls
中的字符串在big
里出现的所有位置positions
,其中positions[i]
为smalls[i]
出现的所有位置。
示例:
输入: big = "mississippi" smalls = ["is","ppi","hi","sis","i","ssippi"] 输出: [[1,4],[8],[],[3],[1,4,7,10],[5]]
提示:
0 <= len(big) <= 1000
0 <= len(smalls[i]) <= 1000
smalls
的总字符数不会超过 100000。- 你可以认为
smalls
中没有重复字符串。 - 所有出现的字符均为英文小写字母。
class Trie {
public:
Trie* next[26] = { nullptr }; //存储可能的下一个字符(小写字母共26位)
int isEnd;
Trie() { isEnd = -1; }
// 从头建立树
void insert(string s, int pos) {
Trie* cur = this;
for (int i = 0; i < s.length(); ++i) {
int t = s[i] - 'a';
if (cur->next[t] == nullptr) {
cur->next[t] = new Trie();
}
cur = cur->next[t];
}
cur->isEnd = pos;
}
};
class Solution {
public:
vector<vector<int>> multiSearch(string big, vector<string>& smalls) {
vector<vector<int>>res(smalls.size());
if(big.size() == 0)
return res;
Trie* head = new Trie;
for (int i = 0; i < smalls.size(); ++i) {
head->insert(smalls[i], i);
}
cout << "sad" <<endl;
for (int i = 0; i < big.size(); ++i) {
Trie *cur = head;
for (int j = i; j < big.size(); ++j) {
int num = big[j] - 'a';
if (cur->next[num] == nullptr)
break;
else if (cur->next[num]->isEnd != -1)
res[cur->next[num]->isEnd].push_back(i);
cur = cur->next[num];
}
}
return res;
}
};