洛谷P1709 隐藏口令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

正解,用两个指针指向头和头的下一个。如果头相同,就利用一个k继续向后比较,如果在某一位失配,直接将答案更不优的指针移到失配的下一位。(因为如果一个个继续移位比较的话,以失配前的点为头的串肯定不如k更优),然后继续比较,直到边界位置。
复杂度应该是O(N)。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int maxn=10000005;
char shu[maxn];
int main()
{
    int n;
    bool flag=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)   cin>>shu[i];
    for(int i=n+1;i<=2*n;i++)   shu[i]=shu[i-n];//现将数组复制一遍
    int i=1,j=2,k=0;
    while(i<=n&&j<=n)
    {
        k=0;
        while(shu[i+k]==shu[j+k]&&k<n) k++;
        if(k==n)
        {
            printf("%d",min(i,j)-1);
            flag=1;
            break;
        }
        if(shu[i+k]>shu[j+k])   i+=k+1;
        else j+=k+1;
        if(i==j) j++;
    }
    if(!flag) printf("%d\n",min(i,j)-1);
    return 0;
}

错解:暴力匹配。洛谷上T一个点。先复制一下数组,然后开始逐位比较。比较到不同的,break掉

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int maxn=10000005;
char shu[maxn],bj[maxn];
int main()
{

    int l,jl=0;
    scanf("%d",&l);
    for(int i=1;i<=l;i++)    cin>>shu[i];
    for(int i=l+1;i<=2*l;i++)    shu[i]=shu[i-l];
    for(int i=1;i<=l;i++) bj[i]=shu[i];
    for(int i=1;i<l;i++)
    {
        bool flag=0;
        for(int j=1;j<=l;j++)
        {
            if(shu[j+i]<bj[j])
            {
                flag=1;
                break;
            }
            if(shu[j+i]>bj[j]) break;
        }
        if(flag==1)
        {
            jl=i;
            for(int j=1;j<=l;j++)
                bj[j]=shu[j+i];
        }
    }
    printf("%d\n",jl);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值