csuoj 1353: Guessing the Number

这个题我想到要用kmp找到循环节;

但是后面的我就不会做了;

看到题解才知道是字符串的最小表示;

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100005
using namespace std;
 
char s[maxn*2];
int next[maxn];
 
void kmp(int n)
{
    int j=0;
    for(int i=2;i<=n;i++)
    {
        while(j>0&&s[i]!=s[j+1])j=next[j];
        if(s[i]==s[j+1])++j;
        next[i]=j;
    }
}
 
void MinimumRepresentation(int n)
{
    int i=1,j=2,k=0;
    while(1)
    {
        if(i==j)j++;
        else if(s[j]=='0')j++;
        else if(s[i]=='0')i++;
        else if(s[i+k]==s[j+k])k++;
        else if(s[i+k]<s[j+k])
        {
            if(s[i+k]=='0')j=j+k;
            else j=j+k+1;
            k=0;
        }
        else
        {
            if(s[j+k]=='0')i=i+k;
            else i=i+k+1;
            k=0;
        }
        if(i>n||j>n||k>=n) break;
    }
    int t=i<=n?i:j;
    for(int i=t;i<t+n;i++)
        putchar(s[i]);
    puts("");
}
 
 
int main()
{
    //freopen("test0.in","r",stdin);
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s+1);
        n=strlen(s+1);
        bool flag=0;
        for(int i=1;i<=n;i++)
            if(s[i]!='0')flag=1;
        if(flag==0){printf("1%s\n",s+1);continue;}
        kmp(n);
        int m=n-next[n];
        for(int i=m+1;i<=(2*m);i++)
            s[i]=s[i-m];
        MinimumRepresentation(m);
    }
    return 0;
}
View Code

 

 

posted @ 2013-12-11 22:41  Yours1103  阅读(150)  评论(0编辑  收藏  举报