洛谷題目傳送門c++
最小表示是指一個字符串經過循環位移變換(第一個移到最後一個)所能獲得的字典序最小的字符串。spa
由於是環狀的,因此確定要先轉化爲序列,把原串倍長。code
設決策點爲一個表示法的開頭。比較兩個決策點\(i,j\),找到它們的LCP(假設長度爲\(k\))。ip
假設\(s_{i+k}>s_{j+k}\),那麼顯然決策\(s_{i...i+k}\)是分別不優於決策\(s_{j...j+k}\)的,直接跳過這一部分便可。\(s_{i+k}<s_{j+k}\)同理。字符串
時間複雜度\(O(n)\)。get
#include<bits/stdc++.h> #define LL long long #define RG register #define R RG int #define G if(++ip==ie)fread(ip=buf,1,SZ,stdin) using namespace std; const int SZ=1<<19,N=6e5+9; int a[N]; char buf[SZ],*ie=buf+SZ,*ip=ie-1; inline int in(){ G;while(*ip<'-')G; R x=*ip&15;G; while(*ip>'-'){x*=10;x+=*ip&15;G;} return x; } int main(){ R n=in(),i,j,k; for(i=0;i<n;++i)a[i]=a[i+n]=in(); for(i=j=0;i<n&&j<n;(a[i+k]>a[j+k]?i:j)+=k+1){//跳過無用決策 if(i==j)++j;//注意特判 for(k=0;k<n&&a[i+k]==a[j+k];++k);//找LCP } for(i=min(i,j),j=i+n;i<j;++i) printf("%d ",a[i]); puts(""); return 0; }