Revolving Digits

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

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
 
  这道题就是求一个数字循环移位后和原数字大小比对结果的计数,求小于原数的,等于原数的,大于原数的不同的由原数循环移位得到的数的个数。
  由于每个位置只有一个数,考虑对于每个位置O(1)出解。那么对于比较大小的性质,可以发现:一定会有头一段相等,然后接着开始不同,所以可以求LCP。
  然后可以用后缀数组,把原数复制一遍拼接到后面,找到原数的位置,再枚举每个循环移位后的位置,用RMQ求出LCP,然后统计答案;这里我用的扩展KMP,一样求LCP,但感觉更适合这道题,比后缀数组完美些。
  然而还没完,因为要找出不同的数,上面的方法可能重复计数了,再思考其性质,发现若一个数被计K次,那么其他所有的数都被计了K次,又可以发现K是原字串的循环数,再用普通KMP解决就好了。
 #include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=;
int lens,lent,Q,p,cas;
int f[maxn],r[maxn];
char s[maxn],t[maxn];
struct ExKmp{
void Init(){
memset(f,,sizeof(f));
memset(r,,sizeof(r));
s[lens+]='%';t[lent+]='&';
} void Get_Fail(){
f[]=lent;
while(t[+f[]]==t[+f[]])
f[]+=;p=;
for(int i=;i<=lent;i++){
int k=p+f[p]-,L=f[i-p+];
if(i+L-<k)f[i]=L;
else{
f[i]=max(,k-i+);
while(t[+f[i]]==t[i+f[i]])
f[i]+=;p=i;
}
}
} void Exkmp(){
Init();Get_Fail();
while(s[+r[]]==t[+r[]])
r[]++;p=;
for(int i=;i<=lens;i++){
int k=p+r[p]-,L=f[i-p+];
if(i+L-<k)r[i]=L;
else{
r[i]=max(,k-i+);
while(t[+r[i]]==s[i+r[i]])
r[i]+=;p=i;
}
}
}
}kmp; int fail[maxn];
int Get_Rnd(){
fail[]=fail[]=;
for(int i=;i<=lent;i++){
int j=fail[i];
while(j!=&&t[i]!=t[j])j=fail[j];
fail[i+]=t[i]==t[j]?j+:;
}
if(lent-fail[lent]==||lent%(lent-fail[lent]))
return ;
else
return lent/(lent-fail[lent]);
} void Solve(){
kmp.Exkmp();
int rnd=Get_Rnd();
int ans1=,ans2=,ans3=;
for(int i=;i<=lent;i++){
if(r[i]==lent)ans2++;
else if(s[i+r[i]]<t[r[i]+])ans1++;
else if(s[i+r[i]]>t[r[i]+])ans3++;
}
printf("%d %d %d\n",ans1/rnd,ans2/rnd,ans3/rnd);
} int main(){
scanf("%d",&Q);
while(Q--){
scanf("%s",t+);
lent=strlen(t+);
for(int i=;i<=lent;i++)
s[i]=s[lent+i]=t[i];
printf("Case %d:",++cas);
lens=lent*;Solve();
}
return ;
}

字符串(扩展KMP):HDU 4333 Revolving Digits的更多相关文章

  1. 扩展KMP - HDU 4333 Revolving Digits

    Revolving Digits Problem's Link Mean: 给你一个字符串,你可以将该字符串的任意长度后缀截取下来然后接到最前面,让你统计所有新串中有多少种字典序小于.等于.大于原串. ...

  2. HDU 4333 Revolving Digits 扩张KMP

    标题来源:HDU 4333 Revolving Digits 意甲冠军:求一个数字环路移动少于不同数量 等同 于的数字 思路:扩展KMP求出S[i..j]等于S[0..j-i]的最长前缀 推断 nex ...

  3. HDU 4333 Revolving Digits 扩展KMP

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意:给以数字字符串,移动最后若干位到最前边,统计得到的数字有多少比原来大,有多少和原来同样,有多少 ...

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

    http://acm.hdu.edu.cn/showproblem.php?pid=4333 [题意] 给定一个数字<=10^100000,每次将该数的第一位放到放到最后一位,求所有组成的不同的 ...

  5. HDU - 4333 Revolving Digits(扩展KMP)

    http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意 一个数字,依次将第一位放到最后一位,问小于本身的数的个数及等于本身的个数和大于本身的个数,但是要注意 ...

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

    题意:给一个数字,每一次把它的最后一位拿到最前面,一直那样下去,分别求形成的数字小于,等于和大于原来数的个数. SAM乱搞失败 当然要先变SS了 然后考虑每个后缀前长为n个字符,把它跟S比较就行了 如 ...

  7. HDU - 4333 Revolving Digits(拓展kmp+最小循环节)

    1.给一个数字字符串s,可以把它的最后一个字符放到最前面变为另一个数字,直到又变为原来的s.求这个过程中比原来的数字小的.相等的.大的数字各有多少. 例如:字符串123,变换过程:123 -> ...

  8. HDU 4333 Revolving Digits

    扩展KMP的应用 我们发现本题的关键在于如何高效的判断两个同构字符串的大小关系,想到如果能够预处理出每一个同构字符串与原字符串的最长公共前缀,那么直接比较它们不一样的部分就好,扩展KMP正好是用来处理 ...

  9. Hdu 4333 Revolving Digits(Exkmp)

    Revolving Digits Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...

随机推荐

  1. git常见指令

    master : 默认开发分支: origin : 默认远程版本库 初始化操作    $ git config -global user.name <name> #设置提交者名字    $ ...

  2. ip、数字的互转

    # ip ==> 数字 >>> ip2num = lambda x:sum([256**j*int(i) for j,i in enumerate(x.split('.')[: ...

  3. PHP编译安装出错configure: error: mcrypt.h not found. Please reinstall libmcrypt的解决办法

    1.下载libmcrypt wget http://jaist.dl.sourceforge.net/project/mcrypt/Libmcrypt/2.5.8/libmcrypt-2.5.8.ta ...

  4. java开发规范总结_命名规范

    规范需要平时编码过程中注意,是一个慢慢养成的好习惯 1.文件 1.属性文件后缀为properties,并且符合java中i18n的规范:   2.对于各产品模块自己的配置文件必须放置在自己模块的con ...

  5. Linux sz rz

    借助XShell,使用linux命令 root 账号登陆: su root 1.编译安装 wget http://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar. ...

  6. 解决js浮点数计算bug

    1.加 function add(a, b) { var c, d, e; try { c = a.toString().split(".")[1].length; } catch ...

  7. WebService开发步骤

    WebService原理什么的百度很多我就说了,无非就是提供一个接口放在服务端,客户端实现这个接口就可以拿到自己需要的东西. 现在简单说一下用myEclipse来实现服务端和客户端.另一种WebSer ...

  8. CentOS 6.5 IP 设置

    DEVICE=eth0TYPE=EthernetUUID=7d6d54e0-054d-472b-8cc1-080f16ef36c1ONBOOT=yesNM_CONTROLLED=yesBOOTPROT ...

  9. AspNet WebApi: 了解下HttpControllerDispatcher,控制器的创建和执行

    HttpControllerDispatcher作为ASPNET WEB API消息处理管道中重要的部分,负责最后控制器系统的激活,action方法的执行,以及最后的响应生成. HtppControl ...

  10. Zephyr-开发流程

    开发流程 前提1:检查你的Linux主机满足入门指南中规定的最低要求. 具体请参考 :  物联网操作系统-Zephyr 前提2: 确保SDK的环境变量和zephyr项目的环境变量. 终端执行: $ e ...