記事のディレクトリ
1.トピック
単語のリストを考えると、このリストには、文字列SインデックスとインデックスリストAとしてエンコードされます
リストがある場合たとえば、["time", "me", "bell"]
私たちは次のように表すことができるS = "time#bell#"
とindexes = [0, 2, 5]
。
各インデックスのために、我々はまでの文字列を読み込み開始位置にある文字列Sからインデックスすることができます"#"
言葉の私達の前のリストを復元するために、エンド。
そして、エンコーディングのための与えられた単語リストを成功させるために、文字列の最小の長さはどのくらいですか?
示例:
输入: words = ["time", "me", "bell"]
输出: 10
说明: S = "time#bell#" , indexes = [0, 2, 5] 。
提示:
1 <= words.length <= 2000
1 <= words[i].length <= 7
每个单词都是小写字母 。
出典:滞在ボタン(LeetCode)
リンクします。https://leetcode-cn.com/problems/short-encoding-of-words
すべてのネットワークからの控除が著作権を保有。商業転載は、ソースを明記してください許可公式、非商用の転載をご連絡ください。
2.問題解決
2.1逆引き参照の文字列+文字
- 各ストリングは従っ長さに降順で反転されます
- 後で蓄積と「接尾辞」(反転後の接頭辞)に文字列の前に表示された単語を検索し、その後、解答文字列を結合する、または追加しないでください
#和字符串
class Solution {
public:
int minimumLengthEncoding(vector<string>& words) {
for(string& w : words)
reverse(w);//反转每个字符串
sort(words.begin(), words.end(),[&](string& a, string& b){
return a.size() > b.size();//长的在前
});
string ans;
for(string& w : words)
{
size_t pos = ans.find(w);
//在ans里查找,没找到,或者,找到了,但是不是反转后的前缀
if(pos == string::npos || ans[pos-1]!='#')
// 注意["me" ,"mean"]之类的例子
ans += "#"+w;
}
return ans.size();
}
void reverse(string& s)
{
int i = 0, j = s.size()-1;
while(i < j)
swap(s[i++],s[j--]);
}
};
2.2接尾辞木
- 逆に文字列を挿入するプレフィックスツリー(トライ)
- 次のように実装され、ハッシュテーブルメモリサブノードを使用して
class Trie
{
public:
unordered_map<char,Trie*> m;
// bool isEnd = false;
void rev_insert(string& s)
{
Trie* root = this;
for(int i = s.size()-1; i >= 0; --i)
{
if(!(root->m).count(s[i]))
{
Trie* node = new Trie();
root->m.insert(make_pair(s[i],node));
}
root = root->m[s[i]];
}
// root->isEnd = true;
}
};
class Solution {
int len = 0;
public:
int minimumLengthEncoding(vector<string>& words) {
Trie *t = new Trie();
for(string& w : words)
t->rev_insert(w);
dfs(t,0);
return len;
}
void dfs(Trie * root, int count)
{
if(root->m.size()==0)// 是叶子节点
{
len += count+1;// +1是 ‘#’
return;
}
for(auto it = root->m.begin(); it != root->m.end(); ++it)
dfs(it->second, count+1);
}
};