算法题解之滑动窗口

Substring with Concatenation of All Words

寻找所有词连接的子串

思路:由于该字串是所有词典中的词连接的,所以该字串长度固定。因此本题可以看作一个滑动窗口的题。为了去除重复工作,每次滑动一个单词的长度,因此起始位置就有n种(n为单词长度)。每种起始位置的滑动策略如下:

   如果当前窗口满足条件,则窗口只往后移动一个单词,并且下一次只检查最后一个单词(中间的单词肯定满足条件)。

     如果当前窗口不满足条件,则有两种情况:

   1.当前窗口内不满足条件的第一个单词不存在于词典中,则下一个窗口就直接滑到这个单词的下一个单词;

   2.当前窗口内不满足条件的第一个单词存在于词典中,但是这个单词已经被前面用完了,则下一个窗口只往后移动一个单词,并且下一次之间从这个单词开始检查。

 1 public class Solution {
 2     public List<Integer> findSubstring(String s, String[] words) {
 3         List<Integer> res = new ArrayList<Integer>();
 4         int m = words.length;
 5         int n = words[0].length();
 6         Map<String, Integer> map = new HashMap<String, Integer>();
 7         for (String word : words) {
 8             if (map.containsKey(word)) {
 9                 map.put(word, map.get(word) + 1);
10             } else {
11                 map.put(word, 1);
12             }
13         }
14         for (int p = 0; p <= n - 1; p++) {
15             int start = p;
16             while (start + n * m - 1 < s.length()) {
17                 int i = 1;
18                 boolean moveOneWord = true;
19                 Map<String, Integer> copy = new HashMap<String, Integer>(map);
20                 while (moveOneWord && start + n * m - 1 < s.length()) {
21                     for(; i <= m; i++) {
22                         String cut = s.substring(start + (i - 1) * n, start + i * n);
23                         if (copy.containsKey(cut)) {
24                             if (copy.get(cut) == 0) {
25                                 moveOneWord = true;
26                                 break;
27                             } else {
28                                 copy.put(cut, copy.get(cut) - 1);
29                             }
30                         } else {
31                             start += i * n;
32                             i = 1;
33                             moveOneWord = false;
34                             break;
35                         }
36                     }
37
38                     if (i == m + 1) {
39                         res.add(start);
40                         moveOneWord = true;
41                     }
42                     if (moveOneWord) {
43                         String firstword = s.substring(start, start + n);
44                         copy.put(firstword, copy.get(firstword) + 1);
45                         start += n;
46                         i--;
47                     }
48                 }
49             }
50         }
51         return res;
52     }
53 }

时间: 2024-10-12 09:00:14

算法题解之滑动窗口的相关文章

算法复习:滑动窗口

leedcode 209 长度最小的子数组 滑动窗口的思想是: 1.设定前指针和后指针,先向后移动后指针直到满足条件, 2.然后向后移动前指针判断是否仍满足条件, 3.如果不满足条件继续向后移动后指针直到满足条件,找出满足条件的最短序列即可. class Solution { public: int minSubArrayLen(int s, vector<int>& nums) { //先计算部分和 int *donser,sum=0,size=nums.size(); donser

粘包、拆包发生原因滑动窗口、MSS/MTU限制、Nagle算法

[TCP协议](3)---TCP粘包黏包 有关TCP协议之前写过两篇博客: 1.[TCP协议](1)---TCP协议详解 2.[TCP协议](2)---TCP三次握手和四次挥手 一.TCP粘包.拆包图解 假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到字节数是不确定的,故可能存在以下四种情况: 1)服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包 2)服务端一次接受到了两个数据包,D1和D2粘合在一起,称之为TCP粘包 3)服务端分两次读取到了数据包,

TCP数据量--滑动窗口、拥塞窗口、慢启动、Negle算法 经受时延的确认等

TCP的数据流大致可以分为两类,交互数据流与成块的数据流.交互数据流就是发送控制命令的数据流,比如relogin,telnet,ftp命令等等:成块数据流是用来发送数据的包,网络上大部分的TCP包都是这种包. 很明显,TCP在传输这两种类型的包时的效率是不一样的,因此为了提高TCP的传输效率,应该对这两种类型的包采用不同的算法. 总之,TCP的传输原则是尽量减少小分组传输的数量. TCP的交互式数据流 ?         经受时延的确认技术 TCP的交互式数据流通常使用"经过时延的确认"

算法设计与优化策略——滑动窗口

"滑动窗口"和上篇博客中介绍的"等价转换"一样也为一种算法优化的思想.同样,下面通过一个例子,来介绍这种思想.唯一的雪花(Unique snowflake,UVa 11572)输入一个长度为n(n<=10^6)的序列A,找到一个尽量长的连续子序列AL~AR,使得该序列中没有相同的元素.在读完题目以后,我们不难有思路.最简单的思路就是,我们可以通过循环的方法,对每一个元素都找出一它为开头的最长序列(没有相同元素).这个方法也能做出来,但似乎有点太麻烦了.下面,我

第二十四个知识点:描述一个二进制m组的滑动窗口指数算法

第二十四个知识点:描述一个二进制m组的滑动窗口指数算法 简单回顾一下我们知道的. 大量的密码学算法的大数是基于指数问题的安全性,例如RSA或者DH算法.因此,现代密码学需要大指数模幂算法的有效实现.我们应该从一个简化的方案开始思考:计算\(x^a\mod N\),我们可以用指数算法来求\(x^a\),然后再约减到\(N\).然而,对大多数密码算法来说,\(x^a\)都是非常大的.现在,大多数传统的方法能被简单的在每个阶段模\(N\).这回产生一些改进的技术.下面我会介绍一些计算\(X^E \mo

算法--滑动窗口

转载请标明出处http://www.cnblogs.com/haozhengfei/p/a14049ec0869a8125a69f3af37471c77.html 滑动窗口练习题 第8节 滑动窗口练习题 有一个整型数组 arr 和一个大小为 w 的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置. 返回一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值. 以数组为[4,3,5,4,3,3,6,7],w=3为例.因为第一个窗口[4,3,5]的最大值为5,第二个窗口[3

LeetCode-Minimum Window Substring-最小窗口子串-滑动窗口算法(尺取法)

https://oj.leetcode.com/problems/minimum-window-substring/ 线性复杂度的限制下,考虑使用滑动窗口法.这个方法的思路就是维持一个窗口,窗口向右边界扩张以满足限制条件.窗口左边界收缩以尽量使其最小. 注意这个题目可能是一个典型的滑动窗口方法的实现.外部循环移动左边界i,循环内部扩张右边界p以满足限制条件.并且内外都有终止可能. 使用两个map和一个计数变量以快速统计条件限制的满足情况. class Solution { public: int

算法-滑动窗口的中位数(堆)

今天在网上刷了一道关于堆的题,感觉有所收获.因为在这里之前,之前从来没有接触过关于堆的题目. 题意: 给定一个包含 n 个整数的数组,和一个大小为 k 的滑动窗口,从左到右在数组中 滑动这个窗口,找到数组中每个窗口内的中位数.(如果数组个数是偶数,则在 该窗口排序数字后,返回第 N/2 个数字.) 样例: 对于数组 [1,2,7,8,5], 滑动大小 k = 3 的窗口时,返回 [2,7,7] 最初,窗口的数组是这样的: [ | 1,2,7 | ,8,5] , 返回中位数 2; 接着,窗口继续向

luogu题解 UVA11536 【Smallest Sub-Array】最短set区间&amp;滑动窗口

题目链接: https://www.luogu.org/problemnew/show/UVA11536 题目大意: 给定一个\(N,M,K\),构造这样的数列: \(x[1]=1,x[2]=2,x[3]=3\) \(x[i]=(x[i-1]+x[i-2]+x[i-3])\mod M+1(N>=i>=4)\) 然后问你是否存在一个在\(x[1]\)到\(x[n]\)中的区间,使得\([1,K]\)所有元素在其中至少出现过一次. 若存在,输出这个区间最短长度:否则输出\("sequen