2019牛客多校 第七场 A String dp+最小表示法

链接:https://ac.nowcoder.com/acm/contest/887/A
来源:牛客网
 

String

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

A string is perfect if it has the smallest lexicographical ordering among its cyclic rotations.
For example: "0101" is perfect as it is the smallest string among ("0101", "1010", "0101", "1010").

Given a 01 string, you need to split it into the least parts and all parts are perfect.

输入描述:

The first line of the input gives the number of test cases, T (T≤300)T\ (T \leq 300)T (T≤300).  test cases follow.

For each test case, the only line contains one non-empty 01 string. The length of string is not exceed 200.

输出描述:

For each test case, output one string separated by a space.

示例1

输入

复制

4
0
0001
0010
111011110

输出

复制

0
0001
001 0
111 01111 0

题解:dp[i] 表示 前i个字符最少分成了几份符合条件的字符串,每取出一个字符串就最小表示法O(n)判断一下是不是最小的

#include 
using namespace std;
#define INF 0x3f3f3f3f
const int N = 210;
int get_max_min(char *s, int flag) { // 1 ?? 0 ??
    int len = strlen(s);
    int i = 0, j = 1, k = 0, t;
    while(i < len && j < len && k < len) {
        t = s[(i + k) % len] - s[(j + k) % len];
        if(!t) k++;
        else {
            if(flag) {
                if(t > 0) j += k + 1;
                else i += k + 1;
            } else {
                if(t > 0) i += k + 1;
                else j += k + 1;
            }
            if(i == j) j++;
            k = 0;
        }
    }
    return min(i, j) + 1;
}
char str[N];
int dp[N], pre[N], nex[N];
int main() {
    int T, len;
    char tmp[N];
    int cnt, now;
    scanf("%d", &T);
    while(T--) {
        scanf("%s", str + 1);
        len = strlen(str + 1);
        memset(dp, INF, sizeof(dp));
        dp[0] = 0;
        for(int i = 1; i <= len; i++) {
    //      cout << i << " : \n";
            for(int j = 1; j <= i; j++) {
                 
                cnt = 0;
                for(int k = j; k <= i; k++) tmp[cnt++] = str[k];
                tmp[cnt] = '\0';
             
                if(get_max_min(tmp, 0) == 1) {
                    if(dp[j - 1] + 1 < dp[i]) {
                        dp[i] = min(dp[i], dp[j - 1] + 1);
                        pre[i] = j - 1;
                    }
                     
                }
                 
            }
        }
        cnt = len;
    //  cout << pre[cnt] << " " << dp[len] << endl;
        while(cnt) {
            now = pre[cnt];
            nex[now] = cnt;
            cnt = pre[cnt];
        }
        cnt = 0;
        while(cnt != len) {
            for(int i = cnt + 1; i <= nex[cnt]; i++)
                printf("%c", str[i]);
            cnt = nex[cnt];
            printf("%c", " \n"[cnt == len]);
        }
    }
    return 0;
}

 

你可能感兴趣的:(dp,最小最大表示法)