题目描述
给定一个单词列表,我们将这个列表编码成一个索引字符串 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] 。
思路
首先对words反转,然后排序,排序依据如下:挨个字母比较,字母小的靠前,若字母相同则长度长的靠前,这样我们可以将words中的字符串排序,使得具有相同结尾的长字符串始终在前压入。之后再将words反转,然后开始逐个查找,如果能查到且结尾是#,则说明可以压缩,反之则不行
代码
class Solution {
public:
int minimumLengthEncoding(vector<string>& words) {
if (words.size() == 0)
return 0;
string res;
for (int i = 0; i < words.size(); i++)
reverse(words[i].begin(), words[i].end());
sort(words.begin(), words.end(),cmp);
for (int i = 0; i < words.size(); i++)
reverse(words[i].begin(), words[i].end());
res = words[0];
res += '#';
for (int i = 1; i<words.size(); i++)
{
if (res.find(words[i]) != string::npos)
{
if (res[res.find(words[i]) + words[i].size()] != '#')
res += words[i] + '#';
}
else
{
res += words[i] + '#';
}
}
return res.size();
}
static bool cmp(string s1, string s2)
{
int len1 = s1.length();
int len2 = s2.length();
for (int i = 0; i < min(len1, len2); i++)
{
if (s1[i] < s2[i])
return true;
else if (s1[i] > s2[i])
return false;
}
if (len1 > len2)
return true;
else
return false;
}
};