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);
           }
       }
   }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM