题意:给定长度为n的字符串,字符串构成一个环,然后找出来一个位置,以这个位置开始,顺时针或者逆时针构成的字符串字典序最大,求最小的位置,如果同一位置顺逆时针都一样的话优先顺时针。
当时直接套最大最小表示法模板WA了...发现是带有循环节的地方过不去,因为处理逆时针的时候我把字符串逆置了,然后对于abcabc,逆置之后是cbacba,最大表示法求出的位置是1,在转回来是6..但是答案是逆时针的3...赛后然后窝打出next数组,单纯判断一下是否逆置的串是包含循环节的串,但是没过- -套了一个kmp才过...把逆置的串复制一遍拼接到后面,然后再找个串中找出逆置串所在的最大位置...
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<stack>
using namespace std;
#define MAXN 103000
#define ll long long
char t[120000],p[120000];
int nex[120000];
char xx[MAXN],yy[MAXN];
void getnext(char *t,int m)
{
int i,j;
i=0;j=-1;
nex[0]=-1;
while(i<m)
{
if(j==-1||t[i]==t[j]) nex[++i]=++j;
else j=nex[j];
}
}
int kmp(char *s,char *t)
{
int n,m,i,j;
i=j=0;
int ans=0;
n=strlen(s);
m=strlen(t);
// puts(s);
// puts(t);
getnext(t,m);
while(i<n-1&&j<m)
{
if(j==-1||s[i]==t[j])
{
i++;j++;
}
else j=nex[j];
if(j==m)
{
ans=max(ans,i-m);
j=nex[j];
//return i-m+1;
}
}
// printf("%d\n",ans);
return ans;
}
int minmaxstring(char *t,int m)
{
int i,j,k;
i=k=0;
j=1;
while(k<m&&i<m&&j<m)
{
int tep=t[(i+k)%m]-t[(j+k)%m];
if(tep==0) k++;
else
{
if(tep<0) j=(j+k+1);
else i=(i+k+1);
if(i==j) j++;
k=0;
}
}
return min(i,j);
}
int n;
int bj(int a,int b)
{
for(int i=0; i<n; i++)
{
if(t[a]<p[b])
return 1;
else if(t[a]>p[b])
return -1;
a=(a+1)%n;
b=(b+1)%n;
}
return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(t,0,sizeof(t));
memset(p,0,sizeof(p));
scanf("%d",&n);
scanf("%s",t);
for(int i=0; i<n; i++)
{
t[i]=(25-t[i]+'a')+'a';
}
int ans1=minmaxstring(t,n);
for(int i=n-1,j=0; i>=0; i--,j++)
p[j]=t[i];
int ans2=minmaxstring(p,n);
int tep=ans2;
for(int i=0;i<n;i++)
{
xx[i]=xx[n+i]=p[i];
yy[i]=p[tep];
tep=(tep+1)%n;
}
yy[n]='\0';
xx[n+n]='\0';
ans2=kmp(xx,yy);
int c=bj(ans1,ans2);
ans2=n-1-ans2;
if(c>0)
printf("%d 0\n",ans1+1);
else if(c<0)
printf("%d 1\n",ans2+1);
else
{
if(ans1<=ans2)
printf("%d 0\n",ans1+1);
else
printf("%d 1\n",ans2+1);
}
}
return 0;
}