洛谷P1709 [USACO5.5]隐藏口令Hidden Password
2017-07-17 08:26
218 查看
题目描述
有时候程序员有很奇怪的方法来隐藏他们的口令。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
题目翻译来自NOCOW。
USACO Training Section 5.5
//20170523新增数据四组
我们以题目中的数据为例,有如下的一个字符串:
对于这个字符串,我们定义两个指针分别为i和 j分别指向 ‘a′和 ′n′ 即i=0j=1 再定义一个累加器 k 则表示分别以 i和 j为首的字符串的第 k个字符.
根据贪心思想,每一项显然要选最小的最好。在这里 ′n′ 的字典序大于′a′ 那么j显然不会是我们所要的答案那么我们就对j进行移位即j++接下来我们便重复上面的操作
因为i和j所指的值是相同的,所以我们并不能通过比较这一位从而得出这两个字符串的顺序关系所以我们就要对k 进行移位即 k++
我们对i+k 和 j+k 所指的字符进行比较,显然可以得出′b′ 是比′n′ 要更优的那么这时候我们就要对i进行移位,因为在[i,i+k)内我们都已经判断完了,那么我们就可以将i移到 i+k+1 继续接下来的判断。根据如上的操作我们就可以写出如下的伪代码:
但是我们还要考虑以下几个问题
1.当i=j时,我们的操作便无法正常的运行,因为显然的在i=j时,i+k=j+k,这样的话我们的k就会不断的增加从而导致WA
2. i+k 和j+k是可能越界的
3. k是可能大于length的
解决方法如下:
1.当i=j时,j++
2.只要执行(i+k)modlength和(j+k)modlength即可
3.限制k<length ,在k=length 直接返回i和j中位置较前的即可
完整代码如下:
有时候程序员有很奇怪的方法来隐藏他们的口令。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
题目翻译来自NOCOW。
USACO Training Section 5.5
//20170523新增数据四组
我们以题目中的数据为例,有如下的一个字符串:
对于这个字符串,我们定义两个指针分别为i和 j分别指向 ‘a′和 ′n′ 即i=0j=1 再定义一个累加器 k 则表示分别以 i和 j为首的字符串的第 k个字符.
根据贪心思想,每一项显然要选最小的最好。在这里 ′n′ 的字典序大于′a′ 那么j显然不会是我们所要的答案那么我们就对j进行移位即j++接下来我们便重复上面的操作
因为i和j所指的值是相同的,所以我们并不能通过比较这一位从而得出这两个字符串的顺序关系所以我们就要对k 进行移位即 k++
我们对i+k 和 j+k 所指的字符进行比较,显然可以得出′b′ 是比′n′ 要更优的那么这时候我们就要对i进行移位,因为在[i,i+k)内我们都已经判断完了,那么我们就可以将i移到 i+k+1 继续接下来的判断。根据如上的操作我们就可以写出如下的伪代码:
i = 0 ; j = 1 ; k = 0; while(i < length && j < length){ if s[i + k] == s[j + k] k++ if s[i + k] > s[j + k] i = i + k + 1; if s[i + k] < s[j + k] j = j + k + 1; …… }
但是我们还要考虑以下几个问题
1.当i=j时,我们的操作便无法正常的运行,因为显然的在i=j时,i+k=j+k,这样的话我们的k就会不断的增加从而导致WA
2. i+k 和j+k是可能越界的
3. k是可能大于length的
解决方法如下:
1.当i=j时,j++
2.只要执行(i+k)modlength和(j+k)modlength即可
3.限制k<length ,在k=length 直接返回i和j中位置较前的即可
完整代码如下:
#include <bits/stdc++.h> using namespace std; const int maxn=5000110; int n; char s[maxn]; int Mini(int l) { int i,j,k; i=0;j=1;k=0; while(i<l&&j<l) { k=0; while(s[(i+k)%l]==s[(j+k)%l]&&k<l) k++; if(k==l) return (i<j)?i:j; if(s[(i+k)%l]>s[(j+k)%l])i=i+k+1; else j=j+k+1; if(i==j)j++; } return (i<j)?i:j; } int main() { cin>>n; for(int i=0;i<n;i++)cin>>s[i]; int l=Mini(n); cout<<l<<endl; return 0; }
相关文章推荐
- 洛谷p1709 [USACO5.5]隐藏口令Hidden Password
- 【洛谷 P1709】[USACO5.5]隐藏口令Hidden Password
- 洛谷 P1709 [USACO5.5]隐藏口令Hidden Password
- 洛谷P1709 [USACO5.5]隐藏口令Hidden Password
- 【USACO题库】5.5.2 Hidden Password隐藏口令
- Luogu P1709 [USACO5.5]隐藏口令Hidden Password
- [USACO5.5]隐藏口令Hidden Password
- 洛谷P1709 隐藏口令Hidden Password
- [USACO5.5]Hidden Password
- usaco 5.5 Hidden Password(最小表示法求同构)
- 洛谷 P1856 [USACO5.5]矩形周长Picture
- usaco隐藏口令
- 洛谷 1456 隐藏口令 (链表/队列优化)
- 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
- 洛谷 2210 [USACO] Haywire dfs+剪枝
- 洛谷 P3147 [USACO16OPEN]262144
- 洛谷 P1203 [USACO1.1]坏掉的项链Broken Necklace
- 【洛谷2986】【USACO10MAR】伟大的奶牛聚集
- 洛谷 P1948 [USACO08JAN]电话线Telephone Lines【NOIP模拟笨笨的电话线】
- 洛谷——P2737 [USACO4.1]麦香牛块Beef McNuggets