- 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
- 57 lines of C++ from the credited upstream file 1923.cpp.
- The implementation visibly relies on sequence storage, hash 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:3 int longestCommonSubpath(int n, vector<vector<int>>& paths) {4 int l = 0;5 int r = paths[0].size();6 7 while (l < r) {8 const int m = l + (r - l + 1) / 2;9 if (checkCommonSubpath(paths, m))10 l = m;11 else12 r = m - 1;13 }14 15 return l;16 }17 18 static constexpr long kBase = 165'131;19 static constexpr long kHash = 8'417'508'174'513;20 21 22 bool checkCommonSubpath(const vector<vector<int>>& paths, int m) {23 vector<unordered_set<long>> hashSets;24 25 26 for (const vector<int>& path : paths)27 hashSets.push_back(rabinKarp(path, m));28 29 30 for (const long subpathHash : hashSets[0])31 if (ranges::all_of(hashSets,32 [subpathHash](const unordered_set<long>& hashSet) {33 return hashSet.contains(subpathHash);34 }))35 return true;36 37 return false;38 }39 40 41 unordered_set<long> rabinKarp(const vector<int>& path, int m) {42 unordered_set<long> hashes;43 long maxPower = 1;44 long hash = 0;45 for (int i = 0; i < path.size(); ++i) {46 hash = (hash * kBase + path[i]) % kHash;47 if (i >= m)48 hash = (hash - path[i - m] * maxPower % kHash + kHash) % kHash;49 else50 maxPower = maxPower * kBase % kHash;51 if (i >= m - 1)52 hashes.insert(hash);53 }54 return hashes;55 }56};57