zoukankan      html  css  js  c++  java
  • KMA & ex_KMP---Revolving Digits

    HDU  4333

    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
     

    题意:给一个数,从这个数的尾端取一个数字放在前段,循环进行,输出有多少得到的数大于原来的数、等于原来的数、小于原来的数,注意相同的数只计算一次。‘

    思路:使用ex_KMP算法可以得到从第i个字符开始和前缀匹配的最大长度,所以和原来的数进行比较大小时,可以减少比较次数节省时间。由于相同的数只能计算一次,所以可以使用KMP算法找出最小周期,对最小周期的字符进行计算。

    代码如下:

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int nex[100005],nex2[100005];
    int a,b,c;
    char str[100005];
    
    void ex_next(int length)
    {
        ///nex[i]: 以第i位置开始的子串与T的前缀的最大长度;
        int i;
        nex[0]=length;
        for(i=0; i<length-1&&str[i]==str[i+1]; i++); ///前缀都是同一个字母的时候;
        nex[1]=i;
        int a=1;///a为使匹配到最远的地方时的起始匹配地点;
        for(int k=2; k<length; k++)
        {
            int p=a+nex[a]-1,L=nex[k-a];
            if( (k-1)+L>=p )
            {
                int j=(p-k+1)>0?(p-k+1):0;
                while(k+j<length&&str[k+j]==str[j]) j++;
                /// 枚举(p+1,length) 与(p-k+1,length) 区间比较;
                nex[k]=j,a=k;
            }
            else nex[k]=L;
        }
    }
    
    void next_(int len)
    {
        int k=0;
        nex2[0]=0;
        for(int i=1; i<len; i++)
        {
            while(k>0&&str[k]!=str[i])
                k=nex2[k-1];
            if(str[k]==str[i])
                k++;
            nex2[i]=k;
        }
    }
    
    void solve(int len)
    {
        int t,s;
        for(int i=1; i<len; i++)
        {
            t=nex[i];
            if(i+t<len)
            {
                if(str[t+i]>str[t]) c++;
                else   a++;
            }
            else
            {
                s=nex[t];
                if(s<i)
                {
                    if(str[t+s]<str[s]) c++;
                    else  a++;
                }
            }
        }
    }
    
    int main()
    {
        int T,Case=1;
        scanf("%d",&T);
        while(T--)
        {
            a=0;
            b=1;
            c=0;
            scanf("%s",str);
            int len=strlen(str);
            next_(len);
            int minn=len-nex2[len-1];
            if(len%minn==0) str[minn]='';
            else minn=len;
            //cout<<minn<<endl;
            ex_next(minn);
            solve(minn);
            printf("Case %d: %d %d %d
    ",Case++,a,b,c);
        }
        return 0;
    }
  • 相关阅读:
    JS document.execCommand实现复制功能(带你出坑)
    jquery动态添加删除一行数据示例
    SpringBoot SpEL表达式注入漏洞-分析与复现
    Fastjson 1.2.22-24 反序列化漏洞分析
    udf提权原理详解
    ZZCMS v8.2 前台Insert注入+任意文件删除
    安恒杯 3月线上个人赛WriteUp
    SQLI LABS Stacked Part(38-53) WriteUp
    【转】Ubuntu16.04安装docker
    安装部署k8s-版本-1.13
  • 原文地址:https://www.cnblogs.com/chen9510/p/5350164.html
Copyright © 2011-2022 走看看