题目链接:点击查看
题目大意:给出一个字符串 s ,需要求出一个 k ,满足 i ∈ [ 1 , n - k + 1 ]中,每个s[ i : i + k - 1 ]都反转一遍,使得最后得到的字符串字典序最小,若有多个 k 满足条件,求出最小的那个 k
题目分析:读完题后最暴力的方法是 n * n * n ,显然是不行的,考虑是否有规律可循,自己手动模拟了一下发现确实有规律,但是比赛的时候没有发现奇偶又别,于是很可惜的被rj掉了,难过
自己拿着abcd和abcde试试就知道规律了:以 k = 3 为例:
abcd -> Cbad -> CD|AB
abcde -> Cbade -> CDabe -> CDE|BA
在最后结果那个部分我加了一个断点,很显然最后的结果由两部分组成:
- 前半部分:s[ k : len ]
- 后半部分:
- 如果 n - k + 1 为奇数:s[ 1 : k ]
- 如果 n - k + 1 为偶数:s[ 1 : k ]翻转
然后n*n暴力维护答案就好了
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=2e5+100;
int main()
{
#ifndef ONLINE_JUDGE
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int w;
cin>>w;
while(w--)
{
int n;
string s;
cin>>n>>s;
int ans=1;
string mmin=s;
for(int k=1;k<n;k++)
{
string temp=s.substr(k);
string rev=s.substr(0,k);
if((n-k+1)%2==0)
reverse(rev.begin(),rev.end());
temp+=rev;
if(temp<mmin)
{
ans=k+1;
mmin=temp;
}
}
cout<<mmin<<endl<<ans<<endl;
}
return 0;
}