题目:
给定一个单词列表,我们将这个列表编码成一个索引字符串 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
每个单词都是小写字母 。
解题思路
方法1: 字典树 字符串数组按照长度大小进行降序排列,并依次放入字典树中;
然后将新单词的长度进行计算(不要忽略‘#’的长度);
方法2: 字符串排序 + 子串匹配
字符串数组按照长度大小进行降序排列,并依次放入char型数组中;
并进行子串匹配(需要连带#一起匹配),如果能够正确匹配则不计算其长度;
分析:
遇到字符串类型题目,如果涉及到前缀/后缀匹配的问题,第一时间想到字典树解法;
之后可以考虑子串匹配(strstr)等解法
//方法1 字典树
#define NUM 26
typedef struct
{
int isWord;
struct Trie *nextList[NUM];
} Trie;
Trie* trieCreate()
{
Trie *root = (Trie*) calloc(1, sizeof(Trie));
return root;
}
bool trieInsert(Trie* obj, char * word)
{
Trie *root = obj;
bool isNewWord = false;
int len = strlen(word);
for (int i = 0; i < len; i++) {
//printf("word = %s,word[i] = %c\n",word, word[i]);
int id = word[i] - 'a';
if (root -> nextList[id] == NULL) {
isNewWord = true;
root -> nextList[id] = trieCreate();
}
root = root -> nextList[id];
}
return isNewWord;
}
//按照长度大小进行降序排列
//字符串 二维数组排序 按照长度大小进行降序排列
int cmp (const void * a, const void * b)
{
return strlen(*(char**)a) < strlen(*(char**)b);
}
void reserve (char * word)
{
int l, r;
l = 0;
r = strlen(word) - 1;
char tmp;
//双指针倒序排列字符串
while (r >= l) {
tmp = word[l];
word[l] = word[r];
word[r] = tmp;
l++;
r--;
}
}
int minimumLengthEncoding(char ** words, int wordsSize)
{
//申请内存
Trie * root = trieCreate();
int len = 0;
//将单词按照长度排列,这样先插入长度长的,直接不会重复插入后缀相同的字符串
qsort(words, wordsSize, sizeof(char*), cmp);
for(int i = 0; i < wordsSize; i++) {
printf("%s\n",words[i] );
}
//倒序写入字典树
//检索所有字符串,如果已经在字典树中,则不进行计数
for (int i = 0; i < wordsSize; i++) {
reserve(words[i]);
if (trieInsert(root, words[i])) {
len += strlen(words[i]) + 1;
}
}
return len;
}
//方法2 排序 + 子串匹配
#define LEN 2000 * 8
int cmp(const void * a, const void * b)
{
return strlen(*(char**)a) < strlen(*(char**)b);
}
int minimumLengthEncoding(char ** words, int wordsSize)
{
//特殊情况
if (words == NULL || wordsSize == 0) {
return 0;
}
//字符串排序
qsort(words, wordsSize, sizeof(char*), cmp);
char * res = calloc (LEN, sizeof(char));
char* cur = res;
char buff[10];
for (int i = 0; i < wordsSize; i++) {
memset(buff, 0, sizeof(char) *10);
sprintf(buff, "%s#", words[i]);
char *tmp = strstr(res, buff);
//可以匹配 则不添加长度
if (NULL != tmp) {
continue;
}
strcat(res, buff);
}
return strlen(res);
}