Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 875 Accepted Submission(s): 240
至于重复串的问题,只有当这个串有循环节的时候才会产生重复串,用KMP的next数组求出最小循环节,用长度除以最小循环节得到循环节个数,在将3个答案都除以循环节个数即可。
//============================================================================ // Name : HDU4333.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <stdio.h> using namespace std; const int MAXN=2000010; int next[MAXN]; int extend[MAXN]; void EKMP(char s[],char t[])//s为主串,t为模板串 { int i,j,p,L; int lens=strlen(s); int lent=strlen(t); next[0]=lent; j=0; while(j+1<lent && t[j]==t[j+1])j++; next[1]=j; int a=1; for(i=2;i<lent;i++) { p=next[a]+a-1; L=next[i-a]; if(i+L<p+1)next[i]=L; else { j=max(0,p-i+1); while(i+j<lent && t[i+j]==t[j])j++; next[i]=j; a=i; } } j=0; while(j<lens && j<lent && s[j]==t[j])j++; extend[0]=j; a=0; for(i=1;i<lens;i++) { p=extend[a]+a-1; L=next[i-a]; if(L+i<p+1)extend[i]=L; else { j=max(0,p-i+1); while(i+j<lens && j<lent && s[i+j]==t[j])j++; extend[i]=j; a=i; } } } void getNext(char T[],int len) { int j,k; j=0;k=-1;next[0]=-1; while(j<len) { if(k==-1 || T[j]==T[k]) next[++j]=++k; else k=next[k]; } } char str1[MAXN],str2[MAXN]; int main() { int T; int iCase=0; scanf("%d",&T); while(T--) { iCase++; scanf("%s",str1); int len=strlen(str1); strcpy(str2,str1); strcat(str2,str1); EKMP(str2,str1); int cnt1=0,cnt2=0,cnt3=0; for(int i=0;i<len;i++) { if(extend[i]>=len)cnt2++; else { if(str2[i+extend[i]]<str1[extend[i]])cnt1++; else cnt3++; } } getNext(str1,len); int t=len-next[len]; int tol=1; if(len%t==0)tol=len/t; printf("Case %d: %d %d %d\n",iCase,cnt1/tol,cnt2/tol,cnt3/tol); } return 0; }