HDU 5442 (最小表示法+next数组循环节)
这题比赛20分钟时候看的,最后一分钟A的。。。
原因就是逆着找的时候要是尽可能后面的,比如abab 倒过来是baba 应该是后面这个b,此时这个对应原串的位置更小
所以用Next数组搞一下。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 50000+50; //开两倍的原因是要复制串长 4 char s[maxn],t[maxn]; 5 char ss[maxn],tt[maxn]; 6 int Next[maxn>>1]; 7 int biggest(int len,char pat[]) //最大表示法 8 { 9 //int len = strlen(pat); 10 int i=0,j=1,k=0; 11 while(i<len && j<len && k<len) 12 { 13 int t = pat[(i+k)%len] - pat[(j+k)%len]; 14 if(!t) k++; 15 else 16 { 17 if(t>0) j = j+k+1; 18 else i = i+k+1; 19 if(i == j) j++; 20 k = 0 ; 21 } 22 } 23 return i<j?i:j; 24 } 25 void getNext(int len) 26 { 27 int i=0,j=-1; 28 Next[0]=-1; 29 while(i<len) 30 { 31 if(j==-1||t[i]==t[j]) 32 i++,j++,Next[i]=j; 33 else 34 j=Next[j]; 35 } 36 } 37 int main() 38 { 39 int test; 40 cin>>test; 41 while(test--) 42 { 43 memset(t,0,sizeof(t)); 44 memset(s,0,sizeof(s)); 45 int len; 46 cin>>len; 47 cin>>s; 48 49 for(int j = 0, i=len-1;i>=0;i--) 50 t[j++]=s[i]; 51 t[len]='\0'; 52 getNext(len); 53 int k1 = biggest(len,s); 54 int k2 = biggest(len,t); 55 int kk1=k1,kk2=k2; 56 for(int i = 0;i < len;i++){ 57 ss[i]=s[k1%len]; 58 k1++; 59 } 60 for(int i = 0;i < len;i++) 61 { 62 tt[i]=t[k2%len]; 63 k2++; 64 } 65 int sum=len-Next[len]; 66 int ans=0; 67 if(len%sum==0) {ans = len/sum; kk2+=(ans-1)*sum;} 68 int tip=0; 69 ss[len]='\0';tt[len] = '\0'; 70 if(strcmp(ss,tt)>0) ans = kk1+1; 71 if(strcmp(ss,tt)<0) ans=(len-kk2),tip=1; 72 if(strcmp(ss,tt)==0) 73 { 74 if((kk1+1)<(len-kk2)) ans=kk1+1; 75 if((kk1+1)>(len-kk2)) ans=(len-kk2),tip=1; 76 if((kk1+1)==(len-kk2)) ans=kk1+1; 77 } 78 cout<<ans<<" "<<tip<<endl; 79 } 80 }
浙公网安备 33010602011771号