洛谷 P1709 [USACO5.5]隐藏口令Hidden Password
题目
题目描述
有时候程序员有很奇怪的方法来隐藏他们的口令。Binny会选择一个字符串S(由N个小写字母组成,5<=N<=5,000,000),然后他把S顺时针绕成一个圈,每次取一个做开头字母并顺时针依次取字母而组成一个字符串。这样将得到一些字符串,他把它们排序后取出第一个字符串。把这个字符串的第一个字母在原字符串中的位置-1做为口令。
如字符串alabala,按操作的到7个字符串,排序后得:
aalabal
abalaal
alaalab
alabala
balaala
laalaba
labalaa
第一个字符串为aalabal,这个a在原字符串位置为7,7-1=6,则6为口令。
输入输出格式
输入格式:
第一行:一个数:N
第二行开始:字符串:S(每72个字符一个换行符)
输出格式:
一行,为得到的口令
输入输出样例
输入样例#1:
7
anabana
输出样例#1:
6
说明
题目满足:
30%的数据n<=10000
70%的数据n<=100000
100%的数据n<=5000000
时限 1s
题解
贪心,先找连续最小字母的字符串的,然后在对比所有这些字符串,选出最优的一个,输出该字符串第一个字母即为答案
代码
#include<cstdio>
#include<cstring>
using namespace std;
int n,j,last,len;
int f[10000005];
char ch,minch;
char a[10000005];
int max(int x,int y)
{
if (x>y) return x;else return y;
}
char min(char x,char y)
{
if (x<y) return x;else return y;
}
int main()
{
scanf("%d",&n);
minch='z';
for (int i=1;i<=n;i++)
{
a[i]=getchar();
while (a[i]<'a'||a[i]>'z') a[i]=getchar();
minch=min(minch,a[i]);
}
for (int i=1;i<n;i++) a[i+n]=a[i];
for (int i=n*2-1;i>=1;i--)
{
if (a[i]==minch) f[i]=f[i+1]+1; else f[i]=0;
len=max(len,f[i]);
}
for (int i=1;i<=n;i++)
{
if (f[i]==len){
if (last==0) last=i;
else{
int j=f[i];
while (n*2-1<=i+j&&a[i+j]==a[last+j]) j++;
if (a[i+j]<a[last+j]) last=i;
}
}
}
printf("%d\n",last-1);
return 0;
}