题目描述
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 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.
示例输入
4
0
0001
0010
111011110
示例输出
0
0001
001 0
111 01111 0
题目大意:
一个字符串,如果本身在它的循环旋转中有最小的字典序,那么它被称为完美字符串。给定一个01字符串,要求将它分成最少的子串,让每个子串都是完美子串。
分析:
要分成最少的子串,那么就是让每个子串要尽可能的长。可以从后往前寻找当前子串的终点,然后用当前终点的下一位置作为下一子串的起点继续寻找。由于本题数据量较小,判定是否为完美子串时,可以直接求出判定范围内的最小字典序串,与当前串比较,相同则该子串完美。
具体解释见代码。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
char str[205];
int f(int index,int eindex){
int n=eindex-index+1;
char tmp[405];
for(int i=1;i<=n;i++){
tmp[i]=tmp[i+n]=str[index+i-1];
}
int i=1,j=2,k;
while(i<=n&&j<=n){
for(k=0;k<n&&tmp[i+k]==tmp[j+k];k++);
if(k==n) break;
if(tmp[i+k]>tmp[j+k]){
i=i+k+1;
if(i==j) i++;
}
else{
j=j+k+1;
if(i==j) j++;
}
}
int ans=min(i,j);//得到最小字典序串的起点在原串中的下标
//比较原串是否等于最小字典序串
int flag=0;
for(int l=ans;l<=ans+n-1;l++){
if(tmp[l]!=tmp[l-ans+1]){
flag=1;
}
}
if(flag){
return false;
}
else{
return true;
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
vector<int> v;
scanf("%s",str+1);
int n=strlen(str+1);
int i=1,j;
while(i<=n){
j=n;
for(;j>=i;j--){
if(f(i,j)){
v.push_back(j);
break;
}
}
i=j+1;
}
int pre=1;
for(int i=0;i<v.size();i++){
for(int j=pre;j<=v[i];j++){
cout<<str[j];
}
cout<<" ";
pre=v[i]+1;
}
cout<<endl;
}
return 0;
}