zoukankan      html  css  js  c++  java
  • LeetCode 30与所有单词相关联的字串

    给定一个字符串 s 和一些长度相同的单词 words。在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置。

    注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

    示例 1:

    输入:
    s = "barfoothefoobarman",
    words = ["foo","bar"]
    输出: [0,9]
    

    解释: 从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
    输出的顺序不重要, [9,0] 也是有效答案。

    示例 2:

    输入:
    s = "wordgoodstudentgoodword",
    words = ["word","student"]
    输出: []
    

    解法

    这道题有一个很关键的条件长度相同的单词,单词长度一致这个题可以退化为单词长度为1来考虑。问题变成:给定一个字符串,寻找由字母集words组成的字串。这种字符串问题就可以考虑使用一个滑窗来解决,扫描源字符串,如果新增单词是单词集words中的单词,并且该单词未在滑窗中出现滑窗增涨(滑窗right增加),否则滑窗缩小(滑窗left增加)。当滑窗满足需求时,记录滑窗左侧(left)的位置,继续扫描,直至无法在生成满足需求的滑窗为止。

    代码

    class Solution {
    
       public List<Integer> findSubstring(String s, String[] words) {
           List<Integer> result = new ArrayList<>();
           if (s == null || s.length() == 0 || words == null || words.length == 0) {
               return result;
           }
           Map<String, Integer> wordsCount = generateCount(words);
           int length = words[0].length();
    
           for (int i = 0; i < length; ++i) {
               Map<String, Integer> window = new HashMap<>();
               int left = i;
               int right = i;
               while (right <= s.length() - length && left <= s.length() - length * words.length) {
                   String sub = s.substring(right, right + length);
                   incr(window, sub);
                   if (!wordsCount.containsKey(sub)) {
                       window.clear();
                       right += length;
                       left = right;
                       continue;
                   }
                   while (window.get(sub) > wordsCount.get(sub)) {
                       decr(window, s.substring(left, left + length));
                       left += length;
                   }
                   right += length;
                   if (right - left == length * words.length) {
                       result.add(left);
                   }
               }
           }
           return result;
       }
    
       private Map<String, Integer> generateCount(String[] words) {
           Map<String, Integer> wordsCount = new HashMap<>();
           for (String word : words) {
               incr(wordsCount, word);
           }
           return wordsCount;
       }
    
       private void incr(Map<String, Integer> map, String key) {
           if (map.containsKey(key)) {
               map.put(key, map.get(key) + 1);
           } else {
               map.put(key, 1);
           }
       }
    
       private void decr(Map<String, Integer> map, String key) {
           if (map.containsKey(key)) {
               Integer value = map.get(key);
               if (value <= 1) {
                   map.remove(key);
               } else {
                   map.put(key, value - 1);
               }
           }
       }
    }
    
  • 相关阅读:
    章程系统管理明天软考的童鞋进来顶起!!!
    线程任务java并发包小结(二)
    模板统计LA 4670 Dominating Patterns
    背包问题选中递归求解0 1背包问题
    转发forwardingiptables remote port forwarding
    函数用户PHP自学之路错误及异常处理机制、错误日志
    内存图片内存溢出和泄漏
    命令视频Matlab下查看摄像头设备信息
    JAVA数据格式化
    数字转大写(java)
  • 原文地址:https://www.cnblogs.com/migoo/p/9454684.html
Copyright © 2011-2022 走看看