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\n",ca++,ans1/xunh,1,ans3/xunh);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/caijiaming/p/11644320.html

时间: 2024-11-05 23:04:46

Revolving Digits(扩展Kmp+最小循环节)的相关文章

HDU 4333 Revolving Digits 扩展KMP

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意:给以数字字符串,移动最后若干位到最前边,统计得到的数字有多少比原来大,有多少和原来相同,有多少比原来的小. 思路:拓展KMP中的next数组标记的是子串和母串的公共前缀的长度,要将字符串长度变成原来二倍,这样如果变换后不是完全相同的数字也即公共前缀长度大于等于字符串长度,那么字母串公共前缀的下一位的大小比较就是题目所要求的比较.由于相同的数字串只算一次,则只要统计比较第一个"循环节"

hdu4333 Revolving Digits 扩展kmp

/** 参考:http://blog.csdn.net/acdreamers/article/details/8313828 参考:http://www.61mon.com/index.php/archives/186/ 题目:hdu4333 Revolving Digits 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意: 给定一个数字(不含前导0),它的最后一个数字放到最前面形成一个新的数字,然后对新的数字继续处理. 问有多少种不同的

HDU 4333 Revolving Digits [扩展KMP]【学习笔记】

题意:给一个数字,每一次把它的最后一位拿到最前面,一直那样下去,分别求形成的数字小于,等于和大于原来数的个数. SAM乱搞失败 当然要先变SS了 然后考虑每个后缀前长为n个字符,把它跟S比较就行了 如果用后缀家族的话复杂度要加上log,本题会TLE吧 求一个串S的每个后缀与另一个串T的最长公共前缀可以用扩展KMP!复杂度O(n+m) 看课件吧 从1开始写真不容易以后再也不从1开始了,判断位置好麻烦好容易错 next[i]=LCP(T[i,m],T) extend[i]=LCP(S[i,n],T)

【扩展kmp+最小循环节】HDU 4333 Revolving Digits

http://acm.hdu.edu.cn/showproblem.php?pid=4333 [题意] 给定一个数字<=10^100000,每次将该数的第一位放到放到最后一位,求所有组成的不同的数比原数小的个数,相等的个数,大的个数 [思路] 这个数很大,用字符串处理 比较两个字符串的大小,一位一位很耗时,可以求出最长公共前缀,只比较最长公共前缀后一位 每次将数的最后一位放到最后一位,如abcd变成dabc,cdab,bcda,相当于abcdabcd各个后缀的前四位 这样就变成了求abcdabc

KMP + 求最小循环节 --- POJ 2406 Power Strings

Power Strings Problem's Link: http://poj.org/problem?id=2406 Mean: 给你一个字符串,让你求这个字符串最多能够被表示成最小循环节重复多少次得到. analyse: KMP之next数组的运用.裸的求最小循环节. Time complexity: O(N) Source code:  /** this code is made by crazyacking* Verdict: Accepted* Submission Date: 20

KMP解决字符串最小循环节相关问题

经典问题 : 给出一个由某个循环节构成的字符串,要你找出最小的循环节,例如 abababab 最小循环节当是 ab ,而类似 abab 也可以成为它的循环节,但并非最短. 分析 : 对于上述问题有两个结论 如果对于next数组中的 i, 符合 i % ( i - next[i] ) == 0 && next[i] != 0 , 则说明字符串循环,而且 循环节长度为:    i - next[i] 循环次数为:       i / ( i - next[i] ) 水平有限,用自己的语言描述怕

poj 1961 Period【求前缀的长度,以及其中最小循环节的循环次数】

Period Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 14653   Accepted: 6965 Description For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the

HDOJ3374 String Problem [KMP最小循环节点]+[最小(大)表示法]

String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1442    Accepted Submission(s): 645 Problem Description Give you a string with length N, you can generate N strings by left shifts

(KMP 1.5)hdu 1358 Period(使用next数组来求最小循环节——求到第i个字符的循环节数)

题目: Period Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3813    Accepted Submission(s): 1862 Problem Description For each prefix of a given string S with N characters (each character has an A