KMA & ex_KMP---Revolving Digits
2016-04-03 17:19
295 查看
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算法找出最小周期,对最小周期的字符进行计算。
代码如下:
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]='\0'; else minn=len; //cout<<minn<<endl; ex_next(minn); solve(minn); printf("Case %d: %d %d %d\n",Case++,a,b,c); } return 0; }
相关文章推荐
- CHEMKIN 4.1 与 CHEMKIN-Pro 4.5 C++ Visual Studio 解决方案
- [bzoj2734][HNOI2012]集合选数
- 表单异步提交
- windowMmanagerService touch事件传递
- leetcode之Power of Three
- HDOJ 2053 Switch Game
- iOS程序优化要点
- 学习Python,学习Pygame(四)
- IOSRadioGroup
- Ruby语言基础学习十一:Ruby异常 和综述
- PHP5.6通过CURL上传图片@符无效的兼容问题
- hdu 4146 Flip Game【思维+暴力】
- Linux内核创建一个新进程的过程
- fork和exec函数
- 获得同级iframe页面的指定ID元素的几种实现方法
- 深入理解letter-spacing和word-spacing2
- 空闲时间继续来学习!!!!!
- linux -grep用法
- 小黑的日常折腾-网段在线地址扫描shell脚本
- JavaScript之jQuery-7 jQuery 使用插件(使用插件、日历插件、表单验证插件)