analysis
Minimum cyclic string problem
Given a string
S
S
S. Each time, you can move its first character to the back to find the string with the smallest dictionary order.
T
T
Group T data (seemingly POJ data compared with water)
Here we first introduce the usage of suffix array idea
Size comparison of a string
If string
A
=
a
1
+
a
2
A = a_1+a_2
A=a1+a2,
B
=
b
1
+
b
2
B = b_1+b_2
B=b1+b2
hypothesis
l
e
n
(
a
1
)
=
=
l
e
n
(
b
1
)
len(a_1) == len(b_1)
len(a1)==len(b1)
If
a
1
<
b
1
a_1<b_1
a1 < B1 then string
A
<
B
A<B
A < B and vice versa
If equal, compare
b
b
The size of b, similarly
!!! Important part!!!
At this time, we can split a binary string into several small strings and compare the size recursively
Then we can use multiplication to solve this problem
set up
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] refers to the current position
i
i
i start, length
2
j
2^j
2j string size ranking. We specify that the ranking here is only for fixed length
2
j
2^j
2j, if the length is not enough, supplement it later
0
0
0, ensure the minimum number of empty characters
initialization
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0] is the value of each character
a
s
c
i
i
ascii
ascii code value
But this transfer needs to be calculated by sorting
So we think of it as above
A
=
a
1
+
a
2
A = a_1 + a_2
A=a1 + a2 will have a length of
2
j
2^j
2j string split into two
2
(
j
−
1
)
2^(j-1)
2(j − 1) small string of length. Quickly sort to get the ranking of the current length. See the following code for details
Time complexity
O
(
n
∗
l
o
g
n
2
)
O(n*logn^2)
O(n∗logn2)
Details:
- Because it is circular, according to the usual routine, break the ring into a chain, and you can splice this string to the end
- Reduce the case of zero filling at the end of special judgment, and double the original size of the array
- Only if the binary split length > 2 N >2N >2n to overwrite all strings
Code [suffix array]
//P1509 /* @Author: YooQ */ //#include <bits/stdc++.h> #include <iostream> #include <algorithm> #include <cstring> using namespace std; #define sc scanf #define pr printf #define ll long long #define int long long #define FILE_OUT freopen("out", "w", stdout); #define FILE_IN freopen("in", "r", stdin); #define debug(x) cout << #x << ": " << x << "\n"; #define max3(a, b, c) max(a, max(b, c)) #define min3(a, b, c) min(a, min(b, c)) #define MAX(a, b) (a >= b ? a : a = b) #define MIN(a, b) (a <= b ? a : a = b) #define AC 0 #define WA 1 #define INF 0x3f3f3f3f const ll MAX_N = 1e6+5; const ll MOD = 1e9+7; const ll UP = 30; int N, M, K; char arr[MAX_N]; int dp[40005][31]; struct Node { int x, y, id; bool operator < (const Node& B) const { return x == B.x ? y < B.y : x < B.x; } }brr[MAX_N]; int limit = 0; bool cmp(int x, int y) { int len = N; for (int i = limit; i+1; --i) { if (len >= (1ll<<i)) { if (dp[x][i] != dp[y][i]) { return dp[x][i] > dp[y][i]; } len -= (1ll<<i); } } return false; } void solve() { cin >> arr+1; N = strlen(arr+1); limit = 0; for (int i = 1; i <= N; ++i) { dp[N+i][0] = dp[i][0] = arr[N+i] = arr[i]; } for (int i = 1; (1ll<<(i-1)) <= N; limit = i++) { for (int j = 1; j <= 2*N; ++j) { brr[j].x = dp[j][i-1]; brr[j].y = dp[j+(1ll<<(i-1))][i-1]; brr[j].id = j; } sort(brr+1, brr+1+2*N); for (int j = 1; j <= 2*N; ++j) { dp[brr[j].id][i] = (brr[j-1].x == brr[j].x && brr[j-1].y == brr[j].y) ? dp[brr[j-1].id][i] : j; } } int ans = 1; for (int i = 2; i <= N; ++i) { if (cmp(ans, i)) { ans = i; } } cout << ans << "\n"; } signed main() { #ifndef ONLINE_JUDGE //FILE_IN FILE_OUT #endif int T = 1; cin >> T; while (T--) solve(); return AC; }
Code [AC automata] - to be supplemented
//todo SAM to solve this problem