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 }

 

你可能感兴趣的:(HDU)