Leetcode30--->Substring with Concatenation of All Words(主串中找出连接给定所有单词的子串的位置)

题目:给定一个字符串S(主串),一个字符串数组words,其中的字符串的长度相同。找到所有的子串位置,要求是words中字符串的一个连接,而且没有交叉;

举例:

For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]

You should return the indices: [0,9].

解题思路:

1. 采用窗口机制,假设此时每个单词的长度为wordlen;

2.   先将words中的单词存储在hashmap中,key为单词,value为单词出现的次数;

3. 在S中以单词长遍历每个单词,看其在hashmap中是否出现,若出现,则窗口的左边界即可确定,然后依次向后遍历,若其中有单词不出现在hashmap中,则直接看下一个单词,窗口的左边界也会更新。若从窗口的左边界遍历找到了与words中单词相拼接的字符串,则将左窗口位置加入到结果集中,左窗口移向下一个单词。

代码如下:

 1 public class Solution {
 2     public List<Integer> findSubstring(String s, String[] words) {
 3         List<Integer> list = new ArrayList<Integer>();
 4         if(s == null || words == null || s.length() < 1 || words.length < 1)
 5             return list;
 6         HashMap<String, Integer> hm = new HashMap<String, Integer>();
 7         for(int i = 0, len = words.length; i < len; i++)   // 将数组中的单词放入到hashmap中,由于数组中有可能有多个相同的单词,所以还需要计数
 8         {
 9             if(hm.containsKey(words[i]))
10                 hm.put(words[i], hm.get(words[i]) + 1);
11             else
12                 hm.put(words[i], 1);
13         }
14         int wordlen = words[0].length(); // 单词的长度
15         int strlen = words.length; // 单词所组成串的长度
16         int i = 0; // 循环的次数
17         int len = s.length();
18         while(i < wordlen)
19         {
20             int left = i; // 窗口的左边界
21             int count = 0; // 匹配了hm中的单词数目
22             HashMap<String, Integer> curr = new HashMap<String, Integer>(); // 记录窗口中已经匹配的单词及其出现的次数
23             for(int j = i; j <= len - wordlen; j = j + wordlen)
24             {
25                 String str = s.substring(j, j + wordlen);  // 取一个单词
26                 if(hm.containsKey(str))  // 如果字典中包含该单词
27                 {
28                     if(curr.containsKey(str))  // 将单词加入到当前遍历的字典中
29                         curr.put(str, curr.get(str) + 1);
30                     else
31                         curr.put(str, 1);
32                     if(hm.get(str) >= curr.get(str))  // str在主串中出现的次数不能小于当前窗口的str出现的次数,否则窗口就要缩小
33                         count ++;
34                     else
35                     {
36                         while(hm.get(str) < curr.get(str))  // 如果当前窗口的单词出现次数大于给定的数组中的单词次数,窗口需要缩小
37                         {
38                             String temp = s.substring(left, left + wordlen);
39                             if(curr.containsKey(temp))
40                             {
41                                  curr.put(temp, curr.get(temp) - 1);
42                                  if(curr.get(temp) < hm.get(temp))
43                                     count--;
44                             }
45                            left += wordlen;
46                         }
47                     }
48                     if(count == strlen)  // 如果此时curr中所保存的单词数量与给定的words中的单词数目是一样的,则将当前窗口的左边缘加入结果
49                     {
50                         list.add(left);
51                         String ss = s.substring(left, left + wordlen);
52                         if(curr.containsKey(ss))
53                         {
54                             curr.put(ss, curr.get(ss) - 1);
55                             count -- ;
56                         }
57                         left += wordlen;
58                     }
59                 }
60                 else  // 如果字典中不包含该单词,则直接看下一个单词
61                 {
62                     left =  j + wordlen;
63                     count  = 0;
64                     curr.clear();
65                 }
66             }
67             i ++;
68         }
69         return list;
70     }
71 }
时间: 2025-01-05 05:15:58

Leetcode30--->Substring with Concatenation of All Words(主串中找出连接给定所有单词的子串的位置)的相关文章

KMP小扩展,找出子串在主串中出现的所有位置

KMP算法能够高效地匹配字符串,找出子串(T串)在主串(S串)中出现的首个位置的原算法网上已经有很多优秀的博文进行详细讲解,这里就不多赘述. 这篇博文主要是对KMP原算法稍作改动,使其能够在主串中把所有匹配的主串找出来. 找出首个匹配的算法好弄,next数组求出来后直接用来匹配,直到出现完全匹配的情况的时候就停止搜索把答案扔出来就行,但是想把所有T串找出来的话就得完全把S串搜完, 就算已经在S串中找到一个T串后也是不能马上停止搜索的. 难点就在已经完全匹配了一个T串以后怎么继续进行下一个匹配.

计算子串在主串中的位置及其优化(KMP算法)

问题描述:设置一个起始位置,寻找主串中第一次出现子串的首位置. 算法实现: int index(string str,string substr,int pos) { int i=0,j=0; int slen,sslen; i=pos; slen=str.length(); sslen=substr.length(); while(i+sslen<slen) { while(j<sslen) { if(str[i+j]==substr[j]) j++; else break; } if(j=

返回主串中子串及其后的所有字符

题目:           写一个函数模拟c++中的strstr函数.该函数的返回值是主串中字符子串的位置以后的所有字符.请不要使用任何c程序已有的函数来完成. #include<iostream> using namespace std; const char* strstr1(const char* string, const char* strCharSet) { for (int i = 0; string[i] != '\0'; i++) { int j = 0; int temp

【通过操作指针,与指针做函数參数&amp;#39;实现字串在主串中出现的次数,然后将出现的部分依照要求进行替换 】

#include<stdio.h> #include<stdlib.h> int strTime(const char *str1, const char *str2, int *time) { int count = 0; char *p1 = str1; char *p2 = str2; //p1是第一次出现的位置 p1 = strstr(p1, p2); //注意这里不要写成*p1!=NULL 由于p1 是null的地址一旦读取*p1 会出错的!!!!不能读取操作系统的数据

通过操作指针,与指针做函数参数&#39;实现字串在主串中出现的次数,然后将出现的部分按照要求进行替换

#include<stdio.h> #include<stdlib.h> int strTime(const char *str1, const char *str2, int *time) { int count = 0; char *p1 = str1; char *p2 = str2; //p1是第一次出现的位置 p1 = strstr(p1, p2); //注意这里不要写成*p1!=NULL 因为p1 是null的地址一旦读取*p1 会出错的!!!!不能读取操作系统的数据

HDU 2087 剪花布条(模式串在主串中出现的次数主串中子串不可重叠)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2087 题意:求模式串在主串中出现的次数,与模式串匹配的子串之间不可重叠. 思路:用kmp算法解决,在匹配更新结果后,重新定位模式串时,不可用j = next[j],应该直接让j定位到模式串开头. code: 1 #include <cstdio> 2 #include <cstring> 3 4 const int MAXN = 1005; 5 6 char aa[MAXN]; 7 c

LeetCode30 Substring with Concatenation of All Words

题目: 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,

Substring with Concatenation of All Words, 返回字符串中包含字符串数组所有字符串元素连接而成的字串的位置

问题描述:给定一个字符数组words,和字符串s,返回字符数组中所有字符元素组成的子串在字符串中的位置,要求所有的字符串数组里的元素只在字符串s中存在一次. 算法分析:这道题和strStr很类似.只不过strStr是子串,而这个题是字符串数组里的元素组成的子串,字符串数组里的元素是无序的,但是必须全部包含.所有考虑使用map集合.关键点在于几个临界值,字符串元素在s中重复了怎么做,找到一个符合的子串后怎么做,有字符串元素不匹配怎做. import java.util.ArrayList; imp

POJ-3461 Oulipo(KMP,模式串在主串中出现次数)

题意:给你两个字符串p和s,求出p在s中出现的次数. 我先想直接把p接到s前面,之后求Next数组对strlen(p)取余==0的就可以,之后WA.最后发现A AASSAAS的时候有bug,只有又想到在p和s中间加个不可能出现的字符'$'就可以了,戒指就A了. #include <bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; typedef long long ll; #define PI(A) printf(&qu