KMA & ex_KMP---Revolving Digits
Posted 茶飘香~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMA & ex_KMP---Revolving Digits相关的知识,希望对你有一定的参考价值。
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.
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; }
以上是关于KMA & ex_KMP---Revolving Digits的主要内容,如果未能解决你的问题,请参考以下文章
jquery懒加载插件 jquery_lazyload 下载