扩展KMP,附上例题(HDU - 4333 Revolving Digits)

给出模板串S和串T,长度分别为Slen和Tlen,在线性时间内,对于每个S[i](0<=i<Slen),求出S[i..Slen-1]与T的

最长公共前缀长度,记为extend[i],extend[i]存放s[i]开始与T的最长公共前缀长度。

例子

    a a a a a a a b b b

    a a a a a c

extend 5 4 3 2 1 0 0 0 0 0

HDU - 4333 Revolving Digits

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

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

题解:给一个数,讲这个数的最后一位放在最前,求这个新的数跟原来的比较大小,最后输出大的,等于的,小的数量

比如有个数字123,先将123两个结合在一起变成123123,进行扩展kmp算法,然后比较y[i+extend[i]] == x[extend[i]]

if(extend[i] >= m) equ++;
else if(y[i+extend[i]] < x[extend[i]]) small++;
else big++;

最后要注意有几个循环结点,除以循环结点

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5
 6 using namespace std;
 7 typedef long long LL;
 8
 9 void pre_EKMP(char x[], int m, int next[]) {
10     next[0] = m;
11     int j = 0;
12     while(j+1<m && x[j] == x[j+1]) j++;
13     next[1] = j;
14     int k = 1;
15     for(int i = 2; i< m; i++) {
16         int p = next[k] + k -1;
17         int L = next[i-k];
18         if(i+L < p+1) next[i] = L;
19         else {
20             j = max(0, p-i+1);
21             while(i+j < m && x[i+j] == x[j]) j++;
22             next[i] = j;
23             k = i;
24         }
25     }
26 }
27
28 void EKMP(char x[], int m, char y[],int n, int next[], int extend[]) {
29     pre_EKMP(x,m,next);
30     int j = 0;
31     while(j <n && j <m && x[j] == y[j]) j++;
32     extend[0] = j;
33     int k = 0;
34     for(int i = 1;i < n ;i++) {
35         int p = extend[k]+k-1;
36         int L=next[i-k];
37         if(i+L < p+1) extend[i] = L;
38         else {
39             j = max(0,p-i+1);
40             while(i+j < n && j < m && y[i+j] == x[j]) j++;
41             extend[i] = j;
42             k = i;
43         }
44     }
45 }
46 int main()
47 {
48     int T;
49     char x[200010],y[200010];
50     int next[200010], extend[200010];
51     int k = 1;
52     scanf("%d",&T);
53     while(T--) {
54         int equ = 0, small = 0, big = 0;
55         scanf("%s",x);
56         strcpy(y,x);
57         strcat(y,x);
58         int m = strlen(x), n = strlen(y);
59         EKMP(x,m,y,n,next,extend);
60         int cnt = 0;
61         for(int i = 0; i < m;i++)//此循环用于判断有几个循环结
62             if(extend[i] == extend[0])
63                 cnt++;
64         for(int i = 0; i < m; i++) {//数值比较大小
65             if(extend[i] >= m) equ++;
66             else if(y[i+extend[i]] < x[extend[i]]) small++;
67             else big++;
68         }
69         printf("Case %d: ",k++);
70         printf("%d %d %d\n",small/cnt,equ/cnt,big/cnt);
71
72     }
73     return 0;
74 }
时间: 2024-12-13 10:57:26

扩展KMP,附上例题(HDU - 4333 Revolving Digits)的相关文章

字符串(扩展KMP):HDU 4333 Revolving Digits

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 int

HDU 4333 Revolving Digits 扩展KMP

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

扩展KMP - HDU 4333 Revolving Digits

Revolving Digits Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=4333 Mean: 给你一个字符串,你可以将该字符串的任意长度后缀截取下来然后接到最前面,让你统计所有新串中有多少种字典序小于.等于.大于原串. analyse: KMP的经典题. 首先我们将原串扩展成两倍,算一遍扩展KMP(自匹配),时间复杂度O(n). 这样一来,我们就得到了eKMP[i],eKMP[i]代表s[i...len-1]与s的最长

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

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

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)

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

1.给一个数字字符串s,可以把它的最后一个字符放到最前面变为另一个数字,直到又变为原来的s.求这个过程中比原来的数字小的.相等的.大的数字各有多少. 例如:字符串123,变换过程:123 -> 312 -> 231 -> 123 因为:312>123, 231>123, 123=123 所以答案是:0 1 2 2.令str1=s,str2=s+s,然后str1作为子串,str2作为主串,进行扩展kmp求出str2[i...len2-1]与str1[0...len1-1]的最长

hdu 4333 Revolving Digits

Revolving Digits http://acm.hdu.edu.cn/showproblem.php?pid=4333 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description One day Silence is interested in revolving the digits of a positive integer. In th

【HDOJ】4333 Revolving Digits

扩展KMP基础题目. 1 /* 4333 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11

状态压缩DP,附上例题(HDU - 1074 Doing Homework )

状态压缩DP:本生有很多状态,然后压缩成一种状态. 很多时候都会使用位运算 Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10077    Accepted Submission(s): 4832 Problem Description Ignatius has just come back school