hdu 4333 扩展kmp

题意:题意:给定一个数字<=10^100000,一次将该数的第一位放到放到最后一位,求所有组成的不同的数比原数小的个数,相等的个数,大的个数

扩展kmp入门题

假如有431,则复制为2个,即,431431,

对该字符串和原穿求ekmp求得extend,求得最长公共前缀,3,0,0,3,0,0,extend【1】=3即表示匹配3位则刚好为原串的长度,则相等,extend【2】=0表示并未存在相同前缀,这时就拿3和4比较,假设extend【2】=1,即存在一个相同前缀,那么只需要和第二位比较即可。

总体来说就是避免不必要的比较

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #include<map>
  8 using namespace std;
  9 const int MAXN=2000010;
 10 
 11 int nextt[MAXN];
 12 int extend[MAXN];
 13 
 14 void pre_EKMP(char x[],int m,int nextt[])
 15 {
 16     nextt[0]=m;
 17     int j=0;
 18     while(j+1<m && x[j]==x[j+1])j++;
 19     nextt[1]=j;
 20     int k=1;
 21     for(int i=2;i<m;i++)
 22     {
 23         int p=nextt[k]+k-1;
 24         int L=nextt[i-k];
 25         if(i+L<p+1)nextt[i]=L;
 26         else
 27         {
 28             j=max(0,p-i+1);
 29             while(i+j<m && x[i+j]==x[j])j++;
 30             nextt[i]=j;
 31             k=i;
 32         }
 33     }
 34 }
 35 void EKMP(char x[],char y[])
 36 {
 37     int n=strlen(y);
 38     int m=strlen(x);
 39     pre_EKMP(x,m,nextt);
 40     int j=0;
 41     while(j<n && j<m && x[j]==y[j])j++;
 42     extend[0]=j;
 43     int k=0;
 44     for(int i=1;i<n;i++)
 45     {
 46         int p=extend[k]+k-1;
 47         int L=nextt[i-k];
 48         if(i+L<p+1)extend[i]=L;
 49         else
 50         {
 51             j=max(0,p-i+1);
 52             while(i+j<n && j<m && y[i+j]==x[j])j++;
 53             extend[i]=j;
 54             k=i;
 55         }
 56     }
 57 }
 58 void getnextt(char T[],int len)
 59 {
 60     int j,k;
 61     j=0;k=-1;
 62     nextt[0]=-1;
 63     while(j<len)
 64     {
 65         if(k==-1 || T[j]==T[k])
 66             nextt[++j]=++k;
 67         else k=nextt[k];
 68     }
 69 }
 70 char str1[MAXN],str2[MAXN];
 71 int main()
 72 {
 73     #ifndef ONLINE_JUDGE
 74     freopen("1.in","r",stdin);
 75     #endif
 76     int T;
 77     int iCase=0;
 78     scanf("%d",&T);
 79     while(T--)
 80     {
 81         iCase++;
 82         scanf("%s",str1);
 83         int len=strlen(str1);
 84         strcpy(str2,str1);
 85         strcat(str2,str1);
 86         EKMP(str1,str2);
 87         /*for(int i=0;i<len*2;i++)
 88         {
 89             printf("%d ",extend[i]);
 90         }
 91         printf("\n");*/
 92         int cnt1=0,cnt2=0,cnt3=0;
 93         for(int i=0;i<len;i++)
 94         {
 95             if(extend[i]>=len)cnt2++;
 96             else
 97             {
 98                 if(str2[i+extend[i]]<str1[extend[i]])cnt1++;
 99                 else cnt3++;
100             }
101         }
102         getnextt(str1,len);
103         int t=len-nextt[len];
104         int tol=1;
105         if(len%t==0)tol=len/t;
106         printf("Case %d: %d %d %d\n",iCase,cnt1/tol,cnt2/tol,cnt3/tol);
107     }
108     return 0;
109 }

 

posted @ 2015-04-29 10:45  miao_a_miao  阅读(155)  评论(0编辑  收藏  举报