Advertisement
i_love_rao_khushboo

Untitled

Jan 21st, 2023
890
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.32 KB | None | 0 0
  1. // METHOD 1
  2.  
  3. // Reference: https://cp-algorithms.com/string/rabin-karp.html
  4. //            https://cp-algorithms.com/string/string-hashing.html
  5.  
  6. #include<bits/stdc++.h>
  7. using namespace std;
  8. #define ll long long
  9.  
  10. const ll p = 31;
  11. const ll mod = 1e9 + 7;
  12.  
  13. ll poly_rolling_hash(string s) {
  14.     // to store the hash value of string
  15.     ll hash = 0;
  16.    
  17.     // since p^0 = 1
  18.     ll p_power = 1;
  19.    
  20.     for(ll i = 0; i < s.length(); i++){
  21.         hash += (p_power * (s[i] - 'a' + 1));
  22.         hash %= mod;
  23.         p_power *= p;
  24.         p_power %= mod;
  25.     }
  26.    
  27.     return hash;
  28. }
  29.  
  30. // fast exponentiation under modulo mod
  31. ll fast_exponent(ll a, ll b) {
  32.     a %= mod;
  33.     if(a == 0) return 0;
  34.    
  35.     ll res = 1LL;
  36.  
  37.     while(b > 0){
  38.         if(b & 1LL) res = (res * a) % mod;
  39.         a = (a * a) % mod;
  40.         b >>= 1LL;
  41.     }
  42.    
  43.     return res;
  44. }
  45.  
  46. // to calculate modulo multiplicative inverse of p under mudulo mod
  47. // fermat's little theorem is used
  48. ll mod_mul_inv(ll p) {
  49.     return fast_exponent(p, mod - 2);
  50. }
  51.  
  52. void rabin_karp(string text, string pat) {
  53.     ll n = text.length();
  54.     ll m = pat.length();
  55.    
  56.     ll text_hash = poly_rolling_hash(text.substr(0, m));
  57.     ll pat_hash = poly_rolling_hash(pat);
  58.    
  59.     if(text_hash == pat_hash){
  60.         cout << "Pattern starting from index: "  << 0 << "\n";
  61.     }
  62.    
  63.     // precompute the mod_mul_inv of p under modulo mod
  64.     ll x = mod_mul_inv(p);
  65.    
  66.     // now try to find the string in the subsequent windows of size m
  67.     for(ll i = 1; i <= (n - m); i++){
  68.         ll curr_hash = text_hash;
  69.        
  70.         // Step 1: remove the contribution of the first character
  71.         // from the hash value of previous window
  72.         curr_hash = (curr_hash - (text[i-1] - 'a' + 1) + mod) % mod;
  73.        
  74.         // Step 2: divide the hash value by p
  75.         // as division is under modulo mod, therefore we can calculate
  76.         // mod_mul_inv of p under modulo mod
  77.         curr_hash *= x;
  78.         curr_hash %= mod;
  79.        
  80.         // Step 3: inculcate the contribution of the last character of the
  81.         // current window
  82.         curr_hash += (fast_exponent(p, m-1) * (text[i + m - 1] - 'a' + 1));
  83.         curr_hash %= mod;
  84.        
  85.         // compare if hashes of text and pattern comes out to be same
  86.         if(curr_hash == pat_hash){
  87.             cout << "Pattern starting from index: "  << i << "\n";
  88.         }
  89.        
  90.         // update for next iteration
  91.         text_hash = curr_hash;
  92.     }
  93. }
  94.  
  95. int main()
  96. {
  97.     ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  98.     srand(chrono::high_resolution_clock::now().time_since_epoch().count());
  99.  
  100.     cout << "Enter the text(haystack): ";
  101.     string text; cin >> text; cout << text <<"\n";
  102.  
  103.     cout << "Enter the pattern to be searched(needle): ";
  104.     string pat; cin >> pat; cout << pat <<"\n";
  105.    
  106.     if(pat.length() > text.length()){
  107.         cout << "Pattern length > Text length" << "\n";
  108.         return;
  109.     }
  110.  
  111.     rabin_karp(text, pat);
  112.    
  113.     return 0;
  114. }
  115.  
  116. /*
  117.  
  118. Sample i/p:
  119.  
  120. aabsgksaabsghaabs
  121. aabs
  122.  
  123. Sample o/p:
  124.  
  125. Enter the text(haystack): aabsgksaabsghaabs
  126. Enter the pattern to be searched(needle): aabs
  127. Pattern starting from index: 0
  128. Pattern starting from index: 7
  129. Pattern starting from index: 13
  130.  
  131. */
  132.  
  133. // Time complexity: O(n + m)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement