• 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?
     
    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.
     
    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):
      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 }
    View Code
  • 相关阅读:
    MongoDB 时间截取、字符串截取、拼接(时间戳、字符串等)
    ClickHouse 参数配置
    C++函数调用栈的变化分析
    WPF中为button添加快捷键(ShortCut)的方法
    vscode中一些好用的插件介绍
    剑指Offer 2. 青蛙跳台阶问题
    切片Slice的使用
    剑指Offer 1. 斐波那契数列
    match_parent和wrap_content的区别
    字节流、字符流
  • 原文地址:https://www.cnblogs.com/oyking/p/3891335.html
Copyright © 2020-2023  润新知