洛谷 P1709 隐藏口令
题目描述
有时候程序员有很奇怪的方法来隐藏他们的口令。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个字符一个换行符)
输出格式:
一行,为得到的口令
输入输出样例
说明
题目满足:
30%的数据n<=10000
70%的数据n<=100000
100%的数据n<=5000000
时限 1s
题目翻译来自NOCOW。
USACO Training Section 5.5
//20170523新增数据四组
分析:
这道题很明显是一个字符串最小表示的问题,在原先的博客中我也发过这个算法,主要是在处理字符串的时候要有特殊的技巧,因为数据量比较大,不能用常规的字符串进行接收。
代码:
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 import java.util.Scanner; 5 6 public class Main { 7 public static void main(String args[]) throws IOException { 8 Scanner sc=new Scanner(System.in); 9 int num=sc.nextInt(); 10 char[] c=new char[num]; 11 String str; 12 int ll; 13 int now=0; 14 while(sc.hasNext()) { 15 str=sc.next(); 16 ll=str.length(); 17 for(int n=0;n<ll;++n) 18 c[now+n]=str.charAt(n); 19 now+=ll; 20 if(now==num) 21 break; 22 } 23 System.out.print(res(c,num)); 24 } 25 public static int res(char[] c,int len) { 26 int i=0,j=1,k=0; 27 while(i<len&&j<len&&k<len) { 28 if(c[(i+k)%len]==c[(j+k)%len]) 29 k++; 30 else if(c[(i+k)%len]<c[(j+k)%len]) { 31 j=j+k+1; 32 k=0; 33 } 34 else { 35 i=j; 36 j=i+1; 37 k=0; 38 } 39 } 40 return i; 41 } 42 }