-
Notifications
You must be signed in to change notification settings - Fork 10
/
rotate-string.cpp
130 lines (118 loc) · 3.25 KB
/
rotate-string.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Time: O(n)
// Space: O(1)
// Rabin-Karp Algorithm (rolling hash)
class Solution {
public:
bool rotateString(string A, string B) {
if (A.length() != B.length()) {
return false;
}
static const uint64_t M = 1000000007;
static const uint64_t p = 113;
static const uint64_t p_inv = pow(p, M - 2, M);
uint64_t b_hash = 0, power = 1;
for (int i = 0; i < B.length(); ++i) {
b_hash += power * B[i];
b_hash %= M;
power = (power * p) % M;
}
uint64_t a_hash = 0; power = 1;
for (int i = 0; i < B.length(); ++i) {
a_hash += power * A[i % A.length()];
a_hash %= M;
power = (power * p) % M;
}
if (a_hash == b_hash && check(0, A, B)) {
return true;
}
power = (power * p_inv) % M;
for (int i = B.length(); i < 2 * A.length(); ++i) {
a_hash -= A[(i - B.length()) % A.length()];
a_hash *= p_inv;
a_hash += power * A[i % A.length()];
a_hash %= M;
if (a_hash == b_hash && check(i - B.length() + 1, A, B)) {
return true;
}
}
return false;
}
private:
bool check(int index, const string& A, const string& B) {
for (int i = 0; i < B.length(); ++i) {
if (A[(i + index) % A.length()] != B[i]) {
return false;
}
}
return true;
}
uint64_t pow(uint64_t a,uint64_t b, uint64_t m) {
a %= m;
uint64_t result = 1;
while (b) {
if (b & 1) {
result = (result * a) % m;
}
a = (a * a) % m;
b >>= 1;
}
return result;
}
};
// Time: O(n)
// Space: O(n)
// KMP algorithm
class Solution2 {
public:
bool rotateString(string A, string B) {
if (A.length() != B.length()) {
return false;
}
return strStr(A + A, B) != -1;
}
private:
int strStr(string haystack, string needle) {
if (needle.empty()) {
return 0;
}
return KMP(haystack, needle);
}
int KMP(const string& text, const string& pattern) {
const vector<int> prefix = getPrefix(pattern);
int j = -1;
for (int i = 0; i < text.length(); ++i) {
while (j > -1 && pattern[j + 1] != text[i]) {
j = prefix[j];
}
if (pattern[j + 1] == text[i]) {
++j;
}
if (j == pattern.length() - 1) {
return i - j;
}
}
return -1;
}
vector<int> getPrefix(const string& pattern) {
vector<int> prefix(pattern.length(), -1);
int j = -1;
for (int i = 1; i < pattern.length(); ++i) {
while (j > -1 && pattern[j + 1] != pattern[i]) {
j = prefix[j];
}
if (pattern[j + 1] == pattern[i]) {
++j;
}
prefix[i] = j;
}
return prefix;
}
};
// Time: O(n^2)
// Space: O(n)
class Solution3 {
public:
bool rotateString(string A, string B) {
return A.size() == B.size() && (A + A).find(B) != string::npos;
}
};