Advertisement
Fastrail08

LIS Memo (Intuitive memo(index, msf))

May 28th, 2025
804
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.69 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. //Used for creating hashing key for pair
  5. // struct pair_hash {
  6. //     template <class T1, class T2>
  7. //     size_t operator()(const pair<T1, T2>& p) const {
  8. //         return hash<T1>()(p.first) ^ (hash<T2>()(p.second) << 1);
  9. //     }
  10. // };
  11.  
  12. // Better Hashing algo than XOR pair hash above
  13. // Used in CP/online judges to avoid TLE
  14. // Better spread out hash keys, so less chaining
  15. struct pair_hash {
  16.     static uint64_t splitmix64(uint64_t x) {
  17.         x += 0x9e3779b97f4a7c15;
  18.         x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
  19.         x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
  20.         return x ^ (x >> 31);
  21.     }
  22.  
  23.     size_t operator()(pair<int, int> p) const {
  24.         uint64_t hash1 = splitmix64(p.first);
  25.         uint64_t hash2 = splitmix64(p.second);
  26.         return hash1 ^ (hash2 << 1);
  27.     }
  28. };
  29.  
  30.  
  31. // Recursive Code for LIS
  32. int getLIS2(int level, int msf, string psf, vector<int> &v){
  33.     if(level >= v.size()){
  34.         // as we only created the valid subsequences by checking before a call, we can directly take the maximum length of subsequence generated.
  35.         cout << psf << '\n';
  36.         return 0;
  37.     }
  38.     //only include when v[level] > msf (A condition needed to always have increasing subsequence, we can only include those v[level] which are greater than those which are already in the current subsequence, or greater than maximum so far of the current subsequence)
  39.     int sizeOfSubInc = 0, sizeOfSubExc = 0;
  40.     if(v[level] > msf){
  41.         sizeOfSubInc = 1 + getLIS2(level + 1, v[level], psf + to_string(v[level]) + " ", v);
  42.     }
  43.    
  44.     //exclude (exclusion does not affect our validity of subsequence; it should always increase, as no new item was included)
  45.     sizeOfSubExc = getLIS2(level + 1, msf, psf, v);
  46.     return max(sizeOfSubExc, sizeOfSubInc);
  47. }
  48.  
  49. // MEMO CODE using HASH Table
  50. int getLIS2Memo(int level, int msf, vector<int> &v, unordered_map<pair<int, int>, int, pair_hash> &memo){
  51.     if(level >= v.size()){
  52.         // as we only created the valid subsequences by checking before a call, we can directly take the maximum length of subsequence generated.
  53.         return 0;
  54.     }
  55.     //memo check
  56.     if(memo.count(make_pair(level, msf)) > 0){
  57.         return memo[make_pair(level, msf)];
  58.     }
  59.        
  60.     //only include when v[level] > msf (A condition needed to always have increasing subsequence, we can only include those v[level] which are greater than those which are already in the current subsequence, or greater than maximum so far of the current subsequence)
  61.     int sizeOfSubInc = 0, sizeOfSubExc = 0;
  62.     if(v[level] > msf){
  63.         sizeOfSubInc = 1 + getLIS2Memo(level + 1, v[level], v, memo);
  64.     }
  65.    
  66.     //exclude (exclusion does not affect our validity of subsequence; it should always increase, as no new item was included)
  67.     sizeOfSubExc = getLIS2Memo(level + 1, msf, v, memo);
  68.     return memo[make_pair(level, msf)] = max(sizeOfSubExc, sizeOfSubInc);
  69. }
  70.  
  71.  
  72. int main() {
  73.     // your code goes here
  74.     int n;
  75.     cin >> n;
  76.     vector<int> v(n);
  77.     for(int i = 0; i < n; i++){
  78.         cin >> v[i];
  79.     }
  80.     // cout << getLIS2(0, INT_MIN, "", v) << '\n';
  81.    
  82.     //Memo call
  83.     //As our subproblem is uniquely identified with memo(level, msf), we need to create a hash with
  84.     //key = {level, msf} and int to store the LIS for that subproblem
  85.     unordered_map<pair<int, int>, int, pair_hash> memo;
  86.     // reserve space before execution so that less rehashing is required.
  87.     // 1 << 19 = 524288, reserve a bucket of this size (~ 5 lakh unique entries possible, to avoid rehashing with small bucket)
  88.     memo.reserve(1 << 19);
  89.     cout << getLIS2Memo(0, INT_MIN, v, memo) << '\n';
  90. }
  91.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement