先简单介绍一下题意:

   大意就是给你一个只含有0和1的字符串,找出一种分割方法,使得每个分割出的字符串都是在该字符串自循环节中最小的,什么叫该字符串自循环呢?比如0001自循环就会产生0010,0100,1000,110010自循环就会产生100101,001011,010110,101100,011001,110010.说白了就是后一个数到前一个数的位置,然后前一个数到最后边。你要使得分割次数尽量的少,且每一个分割出的串都要是本身自循环串中最小的。


下面说一下我的思路(其实是菜鸡看了标程),说一下自己的理解:
   首先看一下数据范围,题目中的保证每个01字符串的长度都不会超过200,所以可以去暴力枚举,在枚举的时候要注意,由于需要保证分割次数最少,所以每个字符串要尽可能的长,所以枚举时就要从最长的开始,找好起点之后,首次枚举都从起点到字符串末尾,然后慢慢缩小范围,然后找到合适的范围后(即该字符串时自循环中的最小值)再更新起点即可,直至枚举完整个字符串。重点说一下,如何判断枚举出的字符串是不是自循环字符串中的最小值。
   我们知道,对于一串数来说,无论什么进制,最高位数字或权值越大的位上(越靠前的位上)的数字越大,那么这串数字本身就越大,比如199和201,201最高位数字为2,大于199最高位数字1,所以201>199,(果两个数字位数不同,就前边补0,补成相同的,再比如2020和2019,在前两位相同的情况下,第三位数字2>1,所以2020>2019。就用这个思路来判断该字符串是不是自循环字符串中最小值。
   对于自循环来说,我们还可以认为,自循环就是依次让每个数字都做一次最高位,所以对于长度为len的字符串,自循环就有len中方式,也就产生了len个数字,所以我们利用当前字符串的每一位去和自循环产生的字符串的每一位去作比较,如何当前字符串与自循环产生的字符串的相同位上,当前字符串大,那么直接否决,如果小,直接让当前字符串去和下一个自循环字符串去比较(从高位开始比,高位小,总体一定小)
   下面看一下代码:

#include<bits/stdc++.h>
using namespace std;
bool check(string str){
    int len=str.length();
    for(int i=0;i<len;i++){
        for(int j=0;j<len;j++){
            if(str[j]>str[(i+j)%len])
                return false;
            if(str[j]<str[(i+j)%len])
                break;
        }
    }
    return true;  
}
int main(){
    int n;
    cin>>n;
    while(n--){
        string t;
        cin>>t;
        int len=t.length();
        int head=0;
        while(head<len){
            for(int j=len-head;j>0;j--){
                if(check(t.substr(head,j))){
                    cout<<t.substr(head,j);
                    head+=j;
                    if(head<len)
                        cout<<" ";
                    break;
                }
            }
        }
        cout<<endl;
    }
    return 0;
}

   重点就是check函数了,外层的for循环表示以此枚举每个自循环字符串的起始位,i=0就表示第1个数(数组中下标为0)为最高位,i=1就表示第2数为最高位,i=x就表示第x个数为最高位,内层循环表示枚举该字符串的每一个数位,并与产生的自循环字符串的每一个数位相比较,如果自循环字符串最高位即起点是第x位,那么该字符串的第0位对应第x位,第1位对应第x+1位,第2位对应第x+2位,所以第i位对应第x+i位,因为把前边的位放到了后边,所以还要取余。如果遇见了比该字符串小的那么直接false。