You are given a string, s, and a list of words, “words”, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
For example, given:
s: "barfoothefoobarman"
words: ["foo","bar"]
You should return the indices: [0,9]. (order does not matter).
思路:本题本质上与《Longest SubstringWithout Repeating Characters》是一样的。但是要注意几个地方:
”words”中的单词可能会重复;
left指针只能一步一步的走,不能跨越,比如这样的字符串s和words:
s: abcdefghidef
words: [“abc”, ”bcd”, ”cde”, ”def”, “ghi”]
本题还是需要使用hash表来快速判断是否找到了words中的单词,注意hash表中还需要记录该单词出现的次数。
如果没找到,则left++,如果找到了,但是找到的单词的次数已经超过了words中的次数,同样的left++。代码如下:
typedef struct hashnode { char *str; int nums; struct hashnode *next; }HashNode; #define NHASH 31 #define MULT 31 unsigned int hash(char *p) { unsigned int h = 0; for (; *p; p++) h = MULT *h + *p; return h % NHASH; } int isfindword(char *word, HashNode **wordhash, int hashlen) { int hashvalue = hash(word); HashNode *ptr = wordhash[hashvalue]; while(ptr != NULL) { if(ptr->str == NULL) return 0; if(strcmp(ptr->str, word) == 0) { return ptr->nums; } ptr = ptr->next; } return 0; } void freehash(HashNode **wordhash, int hashsize) { int i = 0; HashNode *ptr = NULL; HashNode *qtr = ptr; while(i < hashsize) { ptr = wordhash[i]; while(ptr != NULL) { qtr = ptr; ptr = ptr->next; free(qtr->str); free(qtr); } wordhash[i] = NULL; i++; } return; } int inserttohash(HashNode **map, char *word, int wordlen) { int hashvalue = hash(word); HashNode *hp = map[hashvalue]; HashNode *hq = hp; while(hp != NULL) { if(strcmp(hp->str, word) == 0) { hp->nums += 1; break; } else { hq = hp; hp = hp->next; } } if(hp == NULL) { hp = calloc(1, sizeof(HashNode)); hp->str = calloc(wordlen+1, sizeof(char)); memcpy(hp->str, word, wordlen); hp->nums= 1; if(map[hashvalue] == NULL) map[hashvalue] = hp; else hq->next = hp; } return hp->nums; } int* findSubstring(char* s, char** words, int wordsSize, int* returnSize) { int hashlen = NHASH; HashNode **constwordhash = calloc(hashlen, sizeof(HashNode *)); HashNode **acthash = calloc(hashlen, sizeof(HashNode *)); int i; int hashvalue; int wordlen = strlen(words[0]); for(i = 0; i < wordsSize; i++) { inserttohash(constwordhash, words[i], wordlen); } int findnums = 0; int getindexres = -1; int *res = calloc(strlen(s), sizeof(int)); int resindex = 0; int left = 0; i = left; int forcounts = 0; int tstrlen = strlen(s); while(i < tstrlen && left <= tstrlen-wordsSize*wordlen) { forcounts++; char *word = calloc(wordlen+1, sizeof(char)); memcpy(word, s+i, wordlen); getindexres = isfindword(word, constwordhash, hashlen); if(getindexres == 0 || getindexres < inserttohash(acthash, word, wordlen)) { findnums = 0; left++; i = left; freehash(acthash, hashlen); free(word); continue; } else { free(word); findnums++; if(findnums == wordsSize) { res[resindex++] = left; findnums = 0; left++; i = left; freehash(acthash, hashlen); continue; } i += wordlen; } } *returnSize = resindex; freehash(constwordhash, hashlen); freehash(acthash, hashlen); free(constwordhash); free(acthash); return res; }