HDU 4898 The Revenge of the Princess’ Knight(后缀数组+二分+暴力)(2014 Multi-University Training Contest 4)
Problem Description
There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and can’t refuse any request from the devil. Also, this devil is looking like a very cute Loli.
The devil’s birthday is approaching, of course, she wants some beautiful gift from the king. The king search everywhere in this kingdom, and finds a beautiful ring for her.
For simplicity, we can see this ring as a ring(so it is a cycle!) of lowercase characters with length n.
The king’s cute daughter, WJMZBMR, gets nothing from her father in her birthday. She feels very sad. By the influence of the king and the devil, this kingdom is full of lolicon, some people think the king is unfair to his kawayi daughter, so they form a party called princess’s knight and plan to destroy king’s gift for the devil to make things fair.
The knight of the knight (or the lolicon of the lolicon), a man called z*p, has the chance to destroy the ring now. But due to his limitless of strength, he can only cut this ring into exactly k continuous parts. To please the princess, he want among those part, the maximum one respect to the lexicographical order is minimized. How can he do it?
The devil’s birthday is approaching, of course, she wants some beautiful gift from the king. The king search everywhere in this kingdom, and finds a beautiful ring for her.
For simplicity, we can see this ring as a ring(so it is a cycle!) of lowercase characters with length n.
The king’s cute daughter, WJMZBMR, gets nothing from her father in her birthday. She feels very sad. By the influence of the king and the devil, this kingdom is full of lolicon, some people think the king is unfair to his kawayi daughter, so they form a party called princess’s knight and plan to destroy king’s gift for the devil to make things fair.
The knight of the knight (or the lolicon of the lolicon), a man called z*p, has the chance to destroy the ring now. But due to his limitless of strength, he can only cut this ring into exactly k continuous parts. To please the princess, he want among those part, the maximum one respect to the lexicographical order is minimized. How can he do it?
Input
The first line contains an integer T, denoting the number of the test cases.
For each test case, the first line contains two integers n and k, which are the length of the ring and the parts z*p can cut.
The next line is a string represent the ring.
n <= 1000,1<=k<=n.
T <= 5.
For each test case, the first line contains two integers n and k, which are the length of the ring and the parts z*p can cut.
The next line is a string represent the ring.
n <= 1000,1<=k<=n.
T <= 5.
Output
For each case, output the maximum part in one line.
题目大意:给一个环状字符串,要求分成k个连续子串,使得字典序最大的子串最小。求这个子串。
思路:http://www.cnblogs.com/L-Ecry/p/3888396.html
http://blog.csdn.net/t1019256391/article/details/38347293
PS:据说n≤10W还是能做?
代码(2531MS):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 8 const int MAXN = 2010; 9 10 char s[MAXN]; 11 int sa[MAXN], rank[MAXN], c[MAXN], tmp[MAXN], height[MAXN]; 12 int n, k, T; 13 14 void makesa(int n, int m) { 15 memset(c, 0, m * sizeof(int)); 16 for(int i = 0; i < n; ++i) ++c[rank[i] = s[i]]; 17 for(int i = 1; i < m; ++i) c[i] += c[i - 1]; 18 for(int i = 0; i < n; ++i) sa[--c[rank[i]]] = i; 19 for(int k = 1; k < n; k <<= 1) { 20 for(int i = 0; i < n; ++i) { 21 int j = sa[i] - k; 22 if(j < 0) j += n; 23 tmp[c[rank[j]]++] = j; 24 } 25 int j = c[0] = sa[tmp[0]] = 0; 26 for(int i = 1; i < n; ++i) { 27 if(rank[tmp[i]] != rank[tmp[i - 1]] || rank[tmp[i] + k] != rank[tmp[i - 1] + k]) 28 c[++j] = i; 29 sa[tmp[i]] = j; 30 } 31 memcpy(rank, sa, n * sizeof(int)); 32 memcpy(sa, tmp, n * sizeof(int)); 33 } 34 } 35 36 void calheight(int n) { 37 for(int i = 0, k = 0; i < n; height[rank[i++]] = k) { 38 k -= (k > 0); 39 int j = sa[rank[i] - 1]; 40 while(s[i + k] == s[j + k]) ++k; 41 } 42 } 43 44 int logn[MAXN]; 45 int best[20][MAXN]; 46 47 void init(int n = 2000) { 48 static bool done = false; 49 if(done) return ; 50 logn[0] = -1; 51 for(int i = 1; i <= n; ++i) 52 logn[i] = logn[i - 1] + ((i & (i - 1)) == 0); 53 done = true; 54 } 55 56 void initRMQ(int n) { 57 init(); 58 for(int i = 1; i <= n; ++i) best[0][i] = height[i]; 59 for(int i = 1; i <= logn[n]; ++i) { 60 int ed = n - (1 << i) + 1; 61 for(int j = 1; j <= ed; ++j) 62 best[i][j] = min(best[i - 1][j], best[i - 1][j + (1 << (i - 1))]); 63 } 64 } 65 66 int lcp(int a, int b) { 67 if(a == b) return n; 68 a = rank[a], b = rank[b]; 69 if(a > b) swap(a, b); 70 ++a; 71 int t = logn[b - a + 1]; 72 return min(best[t][a], best[t][b - (1 << t) + 1]); 73 } 74 75 int cmp(int x, int n, int y, int m) { 76 int t = lcp(x, y); 77 if(n > t && m > t) return s[x + t] - s[y + t]; 78 return n - m; 79 } 80 81 struct Node { 82 int pos, len; 83 Node() {} 84 Node(int pos, int len): pos(pos), len(len) {} 85 bool operator < (const Node &rhs) const { 86 return cmp(pos, len, rhs.pos, rhs.len) < 0; 87 } 88 void print() { 89 for(int i = pos; i < pos + len; ++i) 90 putchar(s[i]); 91 puts(""); 92 } 93 }; 94 95 const int MAXV = MAXN >> 1; 96 Node src[MAXV * MAXV]; 97 bool mat[MAXV][MAXV], ban[MAXV]; 98 int go[MAXV], cnt[MAXV]; 99 100 bool check(Node p) { 101 memset(mat, 0, sizeof(mat)); 102 memset(ban, 0, sizeof(ban)); 103 for(int i = 0; i < n; ++i) { 104 go[i] = n; 105 if(cmp(i, n, p.pos, p.len) >= 0) go[i] = min(go[i], min(p.len, lcp(p.pos % n, i))); 106 cnt[i] = go[i]; 107 for(int j = i + 1; j <= i + go[i]; ++j) 108 mat[j % n][i] = true; 109 } 110 for(int _ = 0; _ < n; ++_) { 111 bool flag = false; 112 for(int i = 0; i < n; ++i) if(!ban[i] && !cnt[i]) { 113 ban[i] = flag = true; 114 for(int j = 0; j < n; ++j) cnt[j] -= mat[i][j]; 115 } 116 if(!flag) break; 117 } 118 int c = 0; 119 for(int i = 0; i < n; ++i) if(cnt[i]) cnt[c++] = cnt[i]; 120 for(int st = 0; st < c; ++st) { 121 int x = st, y = 0; 122 while(x < st + c) x += cnt[x % c], ++y; 123 if(c >= k && y <= k) return true; 124 } 125 return false; 126 } 127 128 void solve() { 129 int c = 0; 130 for(int i = 0; i < n; ++i) 131 for(int j = 1; j <= n; ++j) src[c++] = Node(i, j); 132 sort(src, src + c); 133 //c = unique(src, src + c) - src; 134 int l = 0, r = c; 135 while(l < r) { 136 int mid = (l + r) >> 1; 137 //src[mid].print(); 138 if(!check(src[mid])) l = mid + 1; 139 else r = mid; 140 } 141 src[l].print(); 142 } 143 144 int main() { 145 scanf("%d", &T); 146 while(T--) { 147 scanf("%d%d", &n, &k); 148 scanf("%s", s); 149 memcpy(s + n, s, n * sizeof(char)); 150 s[n << 1] = 0; 151 makesa(2 * n + 1, 128); 152 calheight(2 * n); 153 initRMQ(2 * n); 154 solve(); 155 } 156 }