/**
*
* 给定一个字符串 s 和一些 长度相同 的单词 words 。
* 找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
* <p>
* 注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,
* 但不需要考虑 words 中单词串联的顺序
*
*/
public List<Integer> findSubstring(String s, String[] words) {
//定义集合保存索引
ArrayList<Integer> list = new ArrayList<>();
//字符串数组的长度
int strsLen = words.length;
//字符串数组中每个字符串的长度
int wordLen = words[0].length();
//则滑动窗口的长度为 strsLen * wordLen
int windowLen = strsLen * wordLen;
//将字符串数组中字符串存储到哈希表中,key存储字符串,value存储字符串出现的次数
HashMap<String, Integer> map = new HashMap<>();
for (String word : words) {
//如果键存在,返回键所映射的值,如果键不存在返回默认值
Integer value = map.getOrDefault(word, 0);
map.put(word, value + 1);
}
//然后把一个窗口中的字符串拆分成子串存储到哈希表中,如果哈希表相同,则匹配
//字符串s的长度
int strLen = s.length();
for (int i = 0; i < strLen - windowLen + 1; i ++) {
//拿到每一个窗口,并将窗口中的字符串切割为成为为wordLen的子串
String window = s.substring(i, windowLen + i);
String[] subStr = new String[strsLen];
int k = 0;
for (int j = 0; j < windowLen - wordLen + 1; j += wordLen) {
subStr[k] = window.substring(j,j + wordLen);
k++;
}
//存入哈希表中
HashMap<String, Integer> tmpMap = new HashMap<>();
for (String s1 : subStr) {
Integer value = tmpMap.getOrDefault(s1, 0);
tmpMap.put(s1, value + 1);
}
//判断两个哈希表是否相等
boolean flag = true;
//先判断键是否相等,采用你中是否有我,我中是否有你的思路
Set<String> keySet = map.keySet();
Set<String> tmpSet = tmpMap.keySet();
for (String key : keySet) {
if (!tmpSet.contains(key)) {
flag = false;
break;
}
}
if (!flag){
continue;
}
for (String key : tmpSet) {
if (!keySet.contains(key)) {
flag = false;
break;
}
}
if (!flag){
continue;
}
//再由键比较值
for (String key : keySet) {
int integer1 = map.get(key);
int integer2 = tmpMap.get(key);
if (integer1 != integer2) {
flag = false;
}
}
if (!flag){
continue;
}
//过关斩将法,如果前变条件都成立,则此子串满足,添加索引
list.add(i);
}
return list;
}
原文:https://www.cnblogs.com/mx-info/p/14790486.html