30.substring-with-concatenation-of-all-words.java 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import java.util.*;
  2. class Solution {
  3. class Frequency {
  4. int val;
  5. Frequency(int val) {
  6. this.val = val;
  7. }
  8. }
  9. public List<Integer> findSubstring(String s, String[] words) {
  10. List<Integer> res = new ArrayList<>();
  11. int l, m, n;
  12. if ((l = s.length()) == 0 || (m = words.length) == 0 || (n = words[0].length()) == 0)
  13. return res; // String is empty or word list is empty or each word is empty
  14. HashMap<String, Frequency> map = new HashMap<>();
  15. for (String word : words) {
  16. Frequency freq = map.get(word);
  17. if (freq == null) map.put(word, new Frequency(1));
  18. else freq.val++;
  19. } // Count the frequency of each word in the word list
  20. for (int i = 0; i < n; i++) { // Shift one character a time
  21. HashMap<String, Frequency> window = new HashMap<>();
  22. int begin = i, count = 0; // Begin of window, count of words in the window
  23. for (int j = i; j < l - n + 1; j += n) {
  24. String word = s.substring(j, j + n);
  25. Frequency target = map.get(word);
  26. if (target == null) { // Not in the word list, clear window & reset begin
  27. window.clear();
  28. begin = j + n;
  29. count = 0;
  30. continue;
  31. }
  32. Frequency occur = window.get(word); // Move right
  33. if (occur == null) {
  34. occur = new Frequency(1);
  35. window.put(word, occur);
  36. } else {
  37. occur.val++;
  38. }
  39. if (occur.val <= target.val) count++;
  40. while (target.val < occur.val) { // Move left
  41. String remove = s.substring(begin, begin + n);
  42. begin += n;
  43. if (remove.equals(word)) {
  44. occur.val--;
  45. } else {
  46. Frequency freq = window.get(remove);
  47. freq.val--;
  48. count--;
  49. }
  50. }
  51. if (count == m) res.add(begin);
  52. }
  53. }
  54. return res;
  55. }
  56. }