Input: s = “barfoothefoobarman”, words = [“foo”,“bar”]
Output: [0,9]
Explanation: Since words.length == 2 and words[i].length == 3, the concatenated substring has to be of length 6.
The substring starting at 0 is “barfoo”. It is the concatenation of [“bar”,“foo”] which is a permutation of words.
The substring starting at 9 is “foobar”. It is the concatenation of [“foo”,“bar”] which is a permutation of words.
The output order does not matter. Returning [9,0] is fine too.
Input: s = “wordgoodgoodgoodbestword”, words = [“word”,“good”,“best”,“word”]
Output: []
Explanation: Since words.length == 4 and words[i].length == 4, the concatenated substring has to be of length 16.
There is no substring of length 16 is s that is equal to the concatenation of any permutation of words.
We return an empty array.
Input: s = “barfoofoobarthefoobarman”, words = [“bar”,“foo”,“the”]
Output: [6,9,12]
Explanation: Since words.length == 3 and words[i].length == 3, the concatenated substring has to be of length 9.
The substring starting at 6 is “foobarthe”. It is the concatenation of [“foo”,“bar”,“the”] which is a permutation of words.
The substring starting at 9 is “barthefoo”. It is the concatenation of [“bar”,“the”,“foo”] which is a permutation of words.
The substring starting at 12 is “thefoobar”. It is the concatenation of [“the”,“foo”,“bar”] which is a permutation of words.
From: LeetCode
Link: 30. Substring with Concatenation of All Words
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* findSubstring(char * s, char ** words, int wordsSize, int* returnSize) {
// Create hash table for word frequencies
int wordCounts[5000] = {0};
int wordLength = strlen(words[0]);
int totalLength = wordsSize * wordLength;
int sLength = strlen(s);
for (int i = 0; i < wordsSize; ++i) {
for (int j = 0; j < wordsSize; ++j) {
if (strcmp(words[i], words[j]) == 0) {
++wordCounts[i];
}
}
}
// Initialize result array
int* result = (int*)malloc(sizeof(int) * sLength);
*returnSize = 0;
for (int i = 0; i < wordLength; ++i) {
int left = i, count = 0;
int substringCounts[5000] = {0};
for (int j = i; j <= sLength - wordLength; j += wordLength) {
char* substring = strndup(s + j, wordLength);
int k;
for (k = 0; k < wordsSize; ++k) {
if (strcmp(substring, words[k]) == 0) {
++substringCounts[k];
if (substringCounts[k] <= wordCounts[k]) {
++count;
} else {
while (substringCounts[k] > wordCounts[k]) {
char* leftSubstring = strndup(s + left, wordLength);
for (int l = 0; l < wordsSize; ++l) {
if (strcmp(leftSubstring, words[l]) == 0) {
--substringCounts[l];
if (substringCounts[l] < wordCounts[l]) {
--count;
}
break;
}
}
free(leftSubstring);
left += wordLength;
}
}
break;
}
}
free(substring);
if (k == wordsSize) {
memset(substringCounts, 0, sizeof(substringCounts));
count = 0;
left = j + wordLength;
} else if (j + wordLength - left == totalLength && count == wordsSize) {
result[(*returnSize)++] = left;
char* leftSubstring = strndup(s + left, wordLength);
for (int l = 0; l < wordsSize; ++l) {
if (strcmp(leftSubstring, words[l]) == 0) {
--substringCounts[l];
--count;
break;
}
}
free(leftSubstring);
left += wordLength;
}
}
}
return result;
}