hdu4333 扩展KMP
一次将第一个数放到最后一个,求所有不同的数中比原串小的个数,等于个数,大于个数
思路:将原串贴在后面,求一遍与原串的EXKMP,然后利用extend
if extend[i]>=len 等于原串
else if s[i+extend[i]]>s[i] 大于原串
else 小于原串
然后利用KMPdenext数组求出循环节所有值除以循环节即可
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 char S[200005],T[200005]; 6 int next[200005],extend[200005]; 7 void EKMP(char s[],char t[]) 8 { 9 int i,j,lens,lent,a,p,l; 10 lens=strlen(s); 11 lent=strlen(t); 12 13 next[0]=lent; 14 j=0; 15 while (j+1<lent&&t[j]==t[j+1]) j++; 16 next[1]=j; 17 a=1; 18 for (i=2;i<lent;i++) 19 { 20 p=next[a]+a-1; 21 l=next[i-a]; 22 if (i+l<p+1) next[i]=l; 23 else{ 24 j=max(0,p-i+1); 25 while (i+j<lent&&t[i+j]==t[j]) j++; 26 next[i]=j; 27 a=i; 28 } 29 } 30 31 j=0; 32 while (j<lens&&j<lent&&s[j]==t[j]) j++; 33 extend[0]=j; 34 a=0; 35 for (i=1;i<lens;i++) 36 { 37 p=extend[a]+a-1; 38 l=next[i-a]; 39 if (l+i<p+1) extend[i]=l; 40 else{ 41 j=max(0,p-i+1); 42 while (i+j<lens&&j<lent&&s[i+j]==t[j]) j++; 43 extend[i]=j; 44 a=i; 45 } 46 } 47 48 } 49 void getnext(char s[],int n) 50 { 51 int i,j; 52 next[1]=j=0; 53 for (i=2;i<=n;i++) 54 { 55 while (j>0&&s[j+1]!=s[i]) j=next[j]; 56 if (s[j+1]==s[i]) j++; 57 next[i]=j; 58 } 59 } 60 int main() 61 { 62 int Case,t,len,t1,t2,t3,cnt,i; 63 scanf("%d",&Case); 64 for (t=1;t<=Case;t++) 65 { 66 scanf("%s",S); 67 len=strlen(S); 68 strcpy(T,S); strcat(T,S); 69 EKMP(T,S); 70 t1=t2=t3=0; 71 for (i=0;i<len;i++) 72 if (extend[i]>=len) t2++; 73 else if (T[i+extend[i]]<S[extend[i]]) t1++; 74 else t3++; 75 for (i=len;i>=1;i--) T[i]=S[i-1]; 76 getnext(T,len); 77 if (len%(len-next[len])!=0) cnt=1; 78 else cnt=len/(len-next[len]); 79 printf("Case %d: %d %d %d\n",t,t1/cnt,t2/cnt,t3/cnt); 80 } 81 return 0; 82 }