链接:https://ac.nowcoder.com/acm/contest/887/A
来源:牛客网
时间限制: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
题意:题目定义了一种01字符串s,要求s是所有s首尾循环(把首字符放到尾部)得到的所有字符串中字典序最小的那个,如果不是,就对字符串进行分段,使得分段的数目最小,然后分成的每段子串都符合要求,比如样例0001,所有循环得到的字符串为:0001,0010,0100,1000。其中字典序最小的为0001也就是本身所以直接输出,样例0010就分成了001和0两个部分。
题解:题目意思很简单,但是不好找,一开始我是先写个暴力的算法来作为测试代码,暴力的写法就是每次从字符串s一个确定的位置依次遍历,找出最长的满足题目要求的部分子串,也就是双重循环,字符串总长度200,平方就是40000,再加上t和其中一些判断的处理,绝对超时,但是我考虑到数据长度为200就不可能是那种想想就得出答案的极端思维题,于是用Python生成了几百组数据用来看规律,果然可以确定的是,除了全是0或者1的特殊字符串,其他的字符串如果要分段,分成的每部分满足题目要求的子串开头一定是0,末尾一定是1(字符串0101100分段,最后一段为00开头和结尾都为0,这个把前面的字符串分好就行),所以定义一个动态数组用来储存10这种关节部分1的位置,然后只针对这些1的位置再进行二重循环遍历,就大大减少了循环次数,提高了效率。
AC代码
#include<bits/stdc++.h>
using namespace std;
bool cmp(string s1,string s2)
{
return s1<s2;
}
vector<string>q;
//用来判断子串是否满足题目要求
bool check(string s)
{
q.clear();
string t;
t=s+s;
for(int i=0;i<s.length();i++)
{
q.push_back(t.substr(i,s.length()));
}
sort(q.begin(),q.end(),cmp);
if(q[0]==s)
return true;
return false;
}
//定义动态数组用来记录10部分1的位置
vector<int>pos;
int main()
{
int t;
// freopen("data.txt","r",stdin);// 按顺序读入(仅此一行)
cin>>t;
string s;
while(t--)
{
// cout<<t<<". ";
cin>>s;
pos.clear();
pos.push_back(-1);
//按要求把1的位置存入数组
for(int i=0;i<s.length();i++)
if(s[i]=='1'&&s[i+1]!='1')
pos.push_back(i);
int i=0,j,st=0;
//开始二重循环遍历
while(i<s.length())
{
//从尾部开始找,如果满足题意就弹出,保证时间效率和答案正确
for(j=pos.size()-1;j>=0;j--)
{
if(pos[j]<i)
{
i++;
break;
}
int len=pos[j]-i+1;
//判断子串是否满足题意
if(check(s.substr(i,len)))
{
cout<<s.substr(i,len)<<" ";
i=pos[j]+1;
st=i;
break;
}
}
}
//这是针对末尾为0的字符串的判断输出,因为我是用1进行判断,如果末尾为0就没法检测到,做特殊判断
for(int k=st+1;k<=i;k++)
printf("%c",s[k-1]);
puts("");
}
return 0;
}