2019牛客暑期多校训练营(第七场)A String

题意:如果一个字符串不是所有循环节里面的最小字典序,就将它分块。问你最少分块之后的字符串。

题解:按照题意模拟就行,这里有几个地方得考虑。暴力队友都认为过不了。。。。但是我认为是可以的,第一个是因为暴力也不能纯的暴力,有很多细节可以优化。

1.判断当前字符串是不是最小的时候,我用的两个字符串相加然后取substr,一个是期望c++能够有点优化。。。一个一个的取就变成n^4了,聊胜于无吧。。(但其实我觉得substr还是on的)

2.代码有两次跳跃,如果取到最小字典序直接跳跃到之后的字符串开始继续跑,这里省略了一部分时间,然后取到如果比当前字符串小的还要break,这里又省略了一部分时间

3.队友觉得过不去的原因是上届为300*200*200*200直接爆炸,我猜测的一个原因是取到上界字符串很少。。。数据很难出,所以稍微优化一下应该没问题

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mem(s) memset(s, 0, sizeof(s))
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 1e6+5;
const int mod = 998244353;
typedef long long ll;
vector<int>res1;
void solve1(string tmp){
    string s=tmp;
    string s1;
    for(int i=0;i<s.size();i++){
        //cout<<i<<endl;
        for(int q=s.size()-i;q>=1;q--){
            s1=s.substr(i,q);
            string tmp2=s1+s1;
            int ff=1;
            for(int j=0;j<s1.size();j++){
                string tmp=tmp2.substr(j,q);
                if(tmp<s1){
                    ff=0;
                    //cout<<s1<<endl;
                    //cout<<tmp<<endl;
                    break;
                }
            }
            if(ff){
                res1.push_back(i+q-1);
                i+=(q-1);
                break;
            }
        }
    }
}

int main()
{
    
    int t;
    scanf("%d",&t);
    while(t--){
        string s;
        cin>>s;string tmp=s;
        res1.clear();
        solve1(s);
        int flag=0;
        //cout<<res1.size()<<endl;
        for(int i=0;i<s.size();i++){
            printf("%c",s[i]);
            if(flag<res1.size()&&i==res1[flag])printf(" "),flag++;
        }
        printf("\n");
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章