最小表示法

http://www.fjutacm.com/Problem.jsp?pid=2411

看到这题,我第一反应简单啊,刷刷刷把代码敲好交了一发

#include<stdio.h>
#include<string.h>
int main()
{
    char s1[200000],s2[200000],s3[200000];
    int l,k;
    while(~scanf("%s",s1)){
        k=0;
        l=strlen(s1);
        strcpy(s3,s1);
        strcpy(s2,s1);
        strcat(s1,s2);
        while(strcmp(s3,s2)>=0){
            k++;
            for(int i=0;i<l;i++){
                s3[i]=s1[i+k];
            }
        }
        puts(s3);
    }
    return 0;
}

不就比较字典序嘛,一个strcmp就解决了,很快啊

然后果不其然

然后寻找大佬帮助,大佬的思路如下:

1.双指针i,j;

2.通过"把已经比较过相等的字符跳过,从最后一个相等的字符的下一个字符开始比较字典序。"的方法降低时间复杂度;

3.然后就是i+k和j+k的三种情况,相等小于大于分别处理;

4.注意事项:i+k要取模防止溢出;i+k和j+k不相等时k=0;i和j相等时i++或者j++,要使它们指向两个不同的位置;

5.最后取i和j里小的那一个。

放代码:

#include<stdio.h>
#include<string.h>
int main()
{
    char s[200005];
    int i,j,l,k,x;
    while(~scanf("%s",s)){
        i=0,j=1,k=0;
        l=strlen(s);
        while(i<l&&j<l&&k<l){
            if(s[(i+k)%l]==s[(j+k)%l])
            k++;
            else if(s[(i+k)%l]<s[(j+k)%l]){
                j=j+k+1;
                if(i==j)
                j++;//i和j要指向不同位置
                k=0;//k要重置为0
            }
            else if(s[(i+k)%l]>s[(j+k)%l]){
                i=i+k+1;
                if(i==j)
                i++;
                k=0;            }
        }
        if(i<j)
        x=i;
        else
        x=j;
        for(int i=0;i<l;i++){
            printf("%c",s[(i+x)%l]);
        }
        printf("
");
    }
    return 0;
}

PS:感谢大佬友情提示!

EOF

原文地址:https://www.cnblogs.com/Untergehen/p/14307292.html