- Choose the invariant that makes a window valid or useful.
- Advance the right boundary and add the new element.
- Move the left boundary only as needed while maintaining the invariant and updating the answer.
Code notes
- 53 lines of Java from the credited upstream file 1923.java.
- The implementation visibly relies on sequence storage, hash lookup, ordered lookup.
- 4 loop blocks detected.
Complexity
Confirm that neither pointer moves backwards; if so, the scan is usually linear apart from the window’s data-structure operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Solution {2 public int longestCommonSubpath(int n, int[][] paths) {3 int l = 0;4 int r = paths[0].length;5 6 while (l < r) {7 final int m = l + (r - l + 1) / 2;8 if (checkCommonSubpath(paths, m))9 l = m;10 else11 r = m - 1;12 }13 14 return l;15 }16 17 private static final long BASE = 165_131L;18 private static final long HASH = 8_417_508_174_513L;19 20 21 private boolean checkCommonSubpath(int[][] paths, int m) {22 Set<Long>[] hashSets = new Set[paths.length];23 24 25 for (int i = 0; i < paths.length; ++i)26 hashSets[i] = rabinKarp(paths[i], m);27 28 29 for (final long subpathHash : hashSets[0])30 if (Arrays.stream(hashSets).allMatch(hashSet -> hashSet.contains(subpathHash)))31 return true;32 33 return false;34 }35 36 37 private Set<Long> rabinKarp(int[] path, int m) {38 Set<Long> hashes = new HashSet<>();39 long maxPower = 1;40 long hash = 0;41 for (int i = 0; i < path.length; ++i) {42 hash = (hash * BASE + path[i]) % HASH;43 if (i >= m)44 hash = (hash - path[i - m] * maxPower % HASH + HASH) % HASH;45 else46 maxPower = maxPower * BASE % HASH;47 if (i >= m - 1)48 hashes.add(hash);49 }50 return hashes;51 }52}53