22#include < vector>
33
44#define q 1000000007l
5- #define x 31
5+ #define x 31 /* <--- overflow with large numbers, all tests passed with x = 1 only; pow() is slow */
66
77class RabinKarp
88{
99public:
1010 RabinKarp (std::string const & pattern, std::string const & text): _pattern(pattern) {
11- // std::cout << __FUNCTION__ << std::endl;
11+
1212 _length = pattern.length ();
13- _patternHash = hash (pattern. c_str () );
13+ _patternHash = hash (pattern);
1414 check (text);
1515 _occ.shrink_to_fit ();
1616 }
1717
1818 ~RabinKarp () {}
1919
2020 void showOccurences () {
21- // std::cout << __FUNCTION__ << std::endl;
21+
2222 for (unsigned i : _occ)
2323 std::cout << i << " " ;
2424 std::cout << std::endl;
2525 }
2626
27- std::vector<unsigned > const & getOccurences () {
28- return _occ;
29- }
27+ std::vector<unsigned > const & getOccurences () { return _occ; }
3028private:
3129 std::vector<unsigned > _occ;
3230 size_t _length;
33- unsigned _patternHash;
31+ long long _patternHash;
3432 std::string _pattern;
3533
3634 void check (std::string const & str) {
37- // std::cout << __FUNCTION__ << std::endl;
35+
3836 size_t i = 1 ;
3937 long long newHash;
4038 long long oldHash;
@@ -44,20 +42,15 @@ class RabinKarp
4442 size_t len = str.length () - _length + 1 ;
4543
4644 oldChar = str[0 ];
47- oldHash = hash (str. c_str () );
45+ oldHash = hash (str);
4846 if (oldHash == _patternHash && equal (str, 0 ))
4947 _occ.push_back (0 );
5048 while (i < len) {
5149 newChar = str[i + _length -1 ];
52- tmp = oldHash - oldChar;
53- tmp = ((tmp % q) + q) %q;
50+ tmp = ((oldHash - oldChar)%q +q)%q;
5451 tmp /= x;
55-
56- newHash = tmp + ( ((newChar * pow (x, _length - 1 ))%q) + q) % q;
52+ newHash = tmp + ((newChar * pow (x, _length - 1 ))%q) % q;
5753 newHash %= q;
58- std::cout << " i = " << i <<" ; oldChar = " << oldChar << " ; oldHash = " << oldHash
59- << " ; newChar = " << newChar << " ; newHash " << newHash << " ; _patternHash: "
60- << _patternHash << std::endl;
6154 if ( newHash == _patternHash && equal (str, i))
6255 _occ.push_back (i);
6356 oldHash = newHash;
@@ -67,7 +60,7 @@ class RabinKarp
6760 }
6861
6962 bool equal (std::string const & str, size_t index) {
70- // std::cout << __FUNCTION__ << std::endl;
63+
7164 size_t i = 0 ;
7265 while (i < _length) {
7366 if (_pattern[i] != str[index])
@@ -79,31 +72,28 @@ class RabinKarp
7972 }
8073
8174 long long pow (long long base, size_t power) {
82- // std::cout << __FUNCTION__ << std::endl;
75+
8376 long long res = 1 ;
8477 if (power == 0 || base == 1 )
8578 return 1 ;
8679 for (size_t i = 0 ; i < power; ++i) {
87- res *= base;
88- res %= q;
80+ res = (res * base)%q;
8981 }
90- return res;
82+ return res % q ;
9183 }
9284
93- long long hash (char const * str) {
94- // std::cout << __FUNCTION__ << std::endl;
85+ long long hash (std::string const & str) {
86+
9587 size_t i = 0 ;
9688 long long res = 0 ;
9789 long long tmp;
9890
9991 while (i < _length) {
10092 tmp = str[i] * pow (x, i);
101- res += tmp %q;
102- tmp = ((tmp%q) + q) %q;
93+ res = (res + tmp) % q;
10394 ++i;
10495 }
105- res = ((res%q) + q)% q;
106- return res;
96+ return res % q;
10797 }
10898};
10999
0 commit comments