详细见:leetcode.com/problems/substring-with-concatenation-of-all-words
Java Solution: github
package leetcode;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
public class P030_SubstringWithConcatenationOfAllWords {
public static void main(String[] args) {
System.out.println(new Solution2().findSubstring("wordgoodgoodgoodbestword", new String[]{"word","good","best","good"}));;
System.out.println(new Solution2().findSubstring("barfoothefoobarman", new String[]{"foo", "bar"}));;
System.out.println(new Solution2().findSubstring("bbbbbb", new String[]{"b", "b", "b", "b"}));;
}
/*
* 土方法,KMP
* 算法正确性没有错
* TLE
* 74 ms
* 44.40%
* 141 ms
* 40.37%
*/
static class Solution1 {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> ans = new LinkedList<Integer>();
int wordlen = 0;
if (s == null || s.length() == 0 || words == null || words.length == 0 || (wordlen = words[0].length()) == 0)
return ans;
char[] sc = s.toCharArray(), wc = null;
int[] sign = new int[sc.length], next = null, judge = new int[words.length];
Arrays.fill(sign, -1); Arrays.fill(judge, 0);
HashMap<String, Integer> judgeMap = new HashMap<String, Integer>();
for (int i = words.length - 1; i != -1; i --) {
if (judgeMap.containsKey(words[i])) {
judge[judgeMap.get(words[i])] ++;
} else {
judgeMap.put(words[i], i);
judge[i] ++;
}
}
// if (judgeMap.size() == 1 && words[0].equals("a")) {
// for (int i = 0; i < s.length() - words.length + 1; i ++)
// ans.add(i);
// return ans;
// }
for (int i = 0; i != words.length; i ++) {
if (judgeMap.get(words[i]) != i)
continue;
wc = words[i].toCharArray();
next = getNext(wc);
int si = 0, pi = 0;
while (si != sc.length) {
if (-1 == pi || sc[si] == wc[pi]) {
si ++; pi ++;
} else
pi = next[pi];
if (pi == wc.length) {
sign[si - wc.length] = i;
si -= wc.length - 1;
pi = 0;
}
}
}
int[] map = new int[words.length];
boolean[] isAdd = new boolean[sign.length];
Arrays.fill(isAdd, false);
for (int i = 0; i != sign.length; i ++) {
if (sign[i] == -1)
continue;
int new_i = 0;
if ((new_i = i - wordlen) > -1) {
int sign_index = words.length * wordlen + new_i;
if (sign_index < sign.length && sign[new_i] == sign[sign_index]) {
isAdd[i] = isAdd[new_i];
if (isAdd[new_i]) {
ans.add(i);
}
continue;
}
}
Arrays.fill(map, 0);
map[sign[i]] ++;
for (int j = 1; j != words.length; j ++) {
int temp = j * wordlen + i;
if (temp >= sign.length || sign[temp] == -1)
break;
map[sign[temp]] ++;
}
boolean isTrue = map[0] == judge[0];
for(int j = 1; j != map.length; j ++)
isTrue &= map[j] == judge[j];
if (isTrue) {
ans.add(i);
isAdd[i] = true;
}
}
return ans;
}
int[] getNext(char[] c) {
int[] next = new int[c.length];
next[0] = -1;
int cur = 0, pre = -1;
while (cur != c.length - 1) {
if (pre == -1 || c[pre] == c[cur]) {
pre ++; cur ++;
next[cur] = pre;
} else
pre = next[pre];
}
return next;
}
}
//AC 30ms 87.95%
static class Solution2 {
public List<Integer> findSubstring(String s, String[] words) {
int len1 = s == null ? 0 : s.length(), len2 = words == null ? 0 : words.length;
LinkedList<Integer> answer = new LinkedList<Integer>();
if (len1 == 0 || len2 == 0) return answer;
HashMap<String, Integer> map1 = new HashMap<String, Integer>(); //保存s上
HashMap<String, Integer> map2 = new HashMap<String, Integer>(); //保存words上
for (String word : words) map2.put(word, map2.getOrDefault(word, 0) + 1);
int wl = words[0].length(), left = 0, count = 0;
for (int i = 0; i < wl; i ++) {
map1.clear();
left = i;
count = 0;
for (int j = i; j <= len1 - wl; j += wl) {
String s1 = s.substring(j, j + wl);
if (map2.containsKey(s1)) {
map1.put(s1, map1.getOrDefault(s1, 0) + 1);
count ++;
while (map1.get(s1) > map2.get(s1)) {
String s2 = s.substring(left, left + wl);
map1.put(s2, map1.get(s2) - 1);
left += wl;
count --;
}
if (count == len2) {
answer.add(left);
String s2 = s.substring(left, left + wl);
map1.put(s2, map1.get(s2) - 1);
left += wl;
count --;
}
} else {
map1.clear();
count = 0;
left = j + wl;
}
}
}
return answer;
}
}
}
C Solution: github
/*
url: leetcode.com/problems/substring-with-concatenation-of-all-words/
46ms 100.0%
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmp(char * s1, int i1, char * s2, int i2, int len) {
int i = 0;
for (i = 0; i < len; i ++) {
if (*(s1 + i1 + i) != *(s2 + i2 + i))
return 0;
}
return 1;
}
int contains(char * s1, char ** record_char, int record_size, int len) {
int i = 0;
for (i = 0; i < record_size; i ++) {
if (cmp(s1, 0, *(record_char + i), 0, len))
return i;
}
return -1;
}
int* findSubstring(char* s, char** words, int len2, int* returnSize) {
int len1 = s == NULL ? 0 : strlen(s);
int wl = 0, left = 0, count = 0, record_size = 1, wi = 0, sign = 1;
int * arr1 = NULL, * arr2 = NULL, i = 0, j = 0, k = 0, v = 0, vv = 0;
char ** record_char = NULL;
int * record_int = NULL, * target_int = NULL;
int * answer = (int *) malloc(sizeof(int) * len1), answer_capacity = len1;
int answer_index = 0, * answer_temp = NULL;
if (len1 == 0 || len2 == 0) return NULL;
wl = strlen(*(words + 0));
for (i = 1; i < len2; i ++) {
for (j = 0, sign = 0; ! sign & (j < i); j ++)
sign |= cmp(*(words + j), 0, *(words + i), 0, wl);
if (! sign) record_size ++;
}
record_char = (char **)(malloc(sizeof(char *) * record_size));
record_int = (int *)(malloc(sizeof(int) * record_size));
target_int = (int *)(malloc(sizeof(int) * record_size));
for (i = 0; i < record_size; i ++) *(target_int + i) = 0;
for (i = 0; i < record_size; i ++) *(record_int + i) = 0;
*(record_char + 0) = *(words + 0);
*(target_int + 0) += 1;
for (i = 1, wi = 1; i < len2; i ++) {
for (j = 0, sign = 0; ! sign & (j < i); j ++)
sign |= cmp(*(words + j), 0, *(words + i), 0, wl);
if (! sign) {
*(record_char + (wi ++)) = *(words + i);
*(target_int + j) += 1;
} else {
*(target_int + j - 1) += 1;
}
}
for (i = 0; i < wl; i ++) {
left = i;
count = 0;
for (k = 0; k < record_size; k ++)
*(record_int + k) = 0;
for (j = i; j <= len1 - wl; j += wl) {
v = contains(s + j, record_char, record_size, wl);
if (v != -1) {
*(record_int + v) += 1;
count ++;
while (*(target_int + v) < *(record_int + v)) {
vv = contains(s + left, record_char, record_size, wl);
*(record_int + vv) -= 1;
count --;
left += wl;
}
if (count == len2) {
//ensure answer size
if (answer_index == answer_capacity) {
answer_temp = (int *)malloc(sizeof(int) * answer_capacity * 2);
for (vv = 0; vv < answer_capacity; vv ++)
answer_temp[vv] = answer[vv];
free(answer);
answer = answer_temp;
answer_capacity = answer_capacity * 2;
}
answer[answer_index ++] = left;
vv = contains(s + left, record_char, record_size, wl);
*(record_int + vv) -= 1;
count --;
left += wl;
}
} else {
left = j + wl;
count = 0;
for (k = 0; k < record_size; k ++)
*(record_int + k) = 0;
}
}
}
* (returnSize + 0) = answer_index;
free(record_char);
free(record_int);
return answer;
}
int main() {
char * s = "bbbbbb";
char ** words = NULL;
char * w0 = "b";
char * w1 = "b";
char * w2 = "b";
char * w3 = "b";
int len2 = 4;
int returnSize = 0;
int * answer = NULL;
int i = 0;
words = (char **)(malloc(sizeof(char *) * len2));
*(words + 0) = w0;
*(words + 1) = w1;
*(words + 2) = w2;
*(words + 3) = w3;
answer = findSubstring(s, words, len2, &returnSize);
for (i = 0; i < returnSize; i ++)
printf("%d ", *(answer + i));
printf("\r\n");
free(words);
free(answer);
return 0;
}
Python Solution: github
#coding=utf-8
'''
url: leetcode.com/problems/substring-with-concatenation-of-all-words/
@author: zxwtry
@email: zxwtry@qq.com
@date: 2017年4月1日
@details: Solution: 82ms 93.41%
'''
class Solution(object):
def findSubstring(self, s, w):
"""
:type s: str
:type w: List[str]
:rtype: List[int]
"""
wn = 0 if w == None else len(w)
sn = 0 if s == None else len(s)
#return invalid
if wn == 0 or sn < sn:
return []
ans, wl, wm, sm = [], len(w[0]), {}, {}
for i in range(wn):
if w[i] in wm:
wm[w[i]] += 1
else: wm[w[i]] = 1
for i in range(wl):
sm.clear()
ii = i
cnt = 0
for j in range(i, sn, wl):
ss = s[j: j + wl]
#continue ss not in wm
#clear all record
if not ss in wm:
sm.clear()
ii = j + wl
cnt = 0
continue
#complete add ss to sm
if ss in sm:
sm[ss] += 1
else:sm[ss] = 1
cnt += 1
#check add valid
while sm[ss] > wm[ss]:
sm[s[ii: ii + wl]] -= 1
ii += wl
cnt -= 1
if cnt == wn:
ans.append(ii)
return ans
if __name__ == "__main__":
s = "barfoofoobarthefoobarman"
w = ["bar","foo","the"]
print(Solution().findSubstring(s, w))
本文提供了LeetCode第30题“包含所有单词的子串”多种编程语言的解决方案,包括Java、C和Python,并针对每种语言提供了解题思路及代码实现。
1717

被折叠的 条评论
为什么被折叠?



