zoukankan      html  css  js  c++  java
  • Revolving Digits(扩展Kmp+最小循环节)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333

    Revolving Digits

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 28267    Accepted Submission(s): 6363


    Problem Description
    One day Silence is interested in revolving the digits of a positive integer. In the revolving operation, he can put several last digits to the front of the integer. Of course, he can put all the digits to the front, so he will get the integer itself. For example, he can change 123 into 312, 231 and 123. Now he wanted to know how many different integers he can get that is less than the original integer, how many different integers he can get that is equal to the original integer and how many different integers he can get that is greater than the original integer. We will ensure that the original integer is positive and it has no leading zeros, but if we get an integer with some leading zeros by revolving the digits, we will regard the new integer as it has no leading zeros. For example, if the original integer is 104, we can get 410, 41 and 104.
     
    Input
    The first line of the input contains an integer T (1<=T<=50) which means the number of test cases.
    For each test cases, there is only one line that is the original integer N. we will ensure that N is an positive integer without leading zeros and N is less than 10^100000.
     
    Output
    For each test case, please output a line which is "Case X: L E G", X means the number of the test case. And L means the number of integers is less than N that we can get by revolving digits. E means the number of integers is equal to N. G means the number of integers is greater than N.
     
    Sample Input
    1 341
     
    Sample Output
    Case 1: 1 1 1
     题意:输入一个整数,长度10^5,可以依次将第一个字符加在最后面,这样可以得到很多个整数,有前导0忽略,问你小于 等于 大于 最初始的数的不同数的
    个数
    思路:扩展kmp的板子题,在原串后面再接一个本身,这样用扩展kmp求出来的数组如果长度>=原串的长度,一定是相等的,不然直接判断nxt[i]+1的大小关系
    但是要注意题目要求的是不同数的个数,所以要去重,每个数算过的次数也就是用kmp求出循环节的长度,自己可以手动推一下
    看代码:
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<fstream>
    #include<string>
    using namespace std;
    typedef long long LL;
    const int maxn=1e5+50;
    const LL mod=1e9+7;
    int nxt[maxn<<1],extend[maxn<<1],next1[maxn<<1];
    int ans1,ans2,ans3;
    string s;
    void cal_next()
    {
        next1[0]=-1;
        int k=-1;
        int len=s.size();
        for(int i=1;i<len;i++)
        {
            while(k>-1&&s[k+1]!=s[i])
            {
                k=next1[k];
            }
            if(s[k+1]==s[i]) k++;
            next1[i]=k;
        }
    }
    void getnxt()
    {
        nxt[0]=s.size();
        int now=0;
        while(s[now]==s[now+1]&&now+1<(int)s.size()) now++;
        nxt[1]=now;
        int p0=1;
        for(int i=2;i<(int)s.size();i++)
        {
            if(i+nxt[i-p0]<nxt[p0]+p0) nxt[i]=nxt[i-p0];
            else
            {
                now=nxt[p0]+p0-i;
                now=max(now,0);
                while(s[now]==s[i+now]&&i+now<(int)s.size()) now++;
                nxt[i]=now;
                p0=i;
            }
        }
    }
    void exkmp()
    {
        getnxt();
        int len=s.size();
        for(int i=0;i<len/2;i++)
        {
            int p=nxt[i];
            if(p>=len/2) ans2++;
            else if(s[i+p]>s[p]) ans3++;
            else ans1++;
        }
    }
    int main()
    {
        int T;scanf("%d",&T);
        int ca=1;
        while(T--)
        {
            ans1=ans2=ans3=0;
            memset(nxt,0,sizeof(nxt));
            memset(extend,0,sizeof(extend));
            memset(next1,0,sizeof(next1));
            cin>>s;
            cal_next();
            int len=s.size();
            int xunh=1;
            if(len%(len-next1[len-1]-1)==0) xunh=len/(len-next1[len-1]-1);
    //        cout<<"xunh:"<<xunh<<endl;
            s+=s;
            exkmp();
            printf("Case %d: %d %d %d
    ",ca++,ans1/xunh,1,ans3/xunh);
        }
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    java网络编程基础——网络基础
    java并发编程基础——线程相关的类
    java并发编程基础——线程池
    java并发编程基础——线程通信
    java并发编程基础——线程同步
    java并发编程基础—生命周期与线程控制
    java并发编程基础——线程的创建
    StreamAPI
    Lambda表达式
    Java Annotation
  • 原文地址:https://www.cnblogs.com/caijiaming/p/11644320.html
Copyright © 2011-2022 走看看