Revolving Digits HDU - 4333 (扩展KMP)

Revolving Digits

 HDU - 4333 

题意:给一串数字,每次可以把最后一个移到最前面形成一个新的数字,问所有的数字中有多少比原数大、小、相等。

原数字为s,长度为len,那么一共形成len数字。

令t=s+s(连接),接下来利用扩展KMP找到t[i]对应的extend[i],然后去和s分三种情况比较。

需要注意的是如果s串是一个循环的串,那么要减去重复的数字,这里用到可KMP,len-nex[len]是循环节的长度。

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=200010;
 4 char s[maxn],t[maxn];
 5 int nex[maxn],ex[maxn];
 6 int lens,lent;
 7 int f[maxn];
 8 void getnex(char* t){
 9     nex[0]=lent;
10     int a=0,p=0;
11     for(int i=1;i<lent;i++){
12         if(i>=p||i+nex[i-a]>=p){
13             if(i>=p) p=i;
14             while(p<lent&&t[p]==t[p-i]) p++;
15             nex[i]=p-i;
16             a=i;
17         }else{
18             nex[i]=nex[i-a];
19         }
20     }
21 }
22 
23 void exkmp(char* s,char* t){
24     int a=0,p=0;
25     getnex(t);
26     for(int i=0;i<lens;i++){
27         if(i>=p||i+nex[i-a]>=p){
28             if(i>=p) p=i;
29             while(i<lens&&p-i<lent&&t[p-i]==s[p]) p++;
30             ex[i]=p-i;
31             a=i;
32         }else {
33             ex[i]=nex[i-a];
34         }
35     }
36 }
37 void getf(char* t){
38     f[0]=f[1]=0;
39     for(int i=1;i<lent;i++){
40         int j=f[i];
41         while(j&&t[i]!=t[j]) j=f[j];
42         f[i+1]=t[i]==t[j]?j+1:0;
43     }
44 }
45 int main(){
46     int T,kase=0;
47     scanf("%d",&T);
48     while(T--){
49         scanf("%s",t);
50         lent=strlen(t);
51         strcpy(s,t);
52         strcat(s,t);
53         lens=lent*2;
54         printf("Case %d:",++kase);
55         exkmp(s,t);
56         int a=0,b=0,c=0;
57         getf(t);
58         int mod=lent-f[lent];
59         int temp=1;
60         if(lent%mod==0) temp=lent/mod;
61         for(int i=0;i<lent;i++){
62             if(ex[i]>=lent) b++;
63             else if(s[i+ex[i]]<t[ex[i]]) a++;
64             else if(s[i+ex[i]]>t[ex[i]]) c++;
65         }
66         printf(" %d %d %d\n",a/temp,b/temp,c/temp);
67     }
68 }
View Code

 

posted @ 2017-08-22 01:30  yijiull  阅读(183)  评论(0编辑  收藏  举报