問題描述:
最小表示法是字串 \(S\) 迴圈同構的所有字串中,字典序最小的串是哪個。
最小表示法:
考慮對於一對字串 \(A,B\), 它們在原字串 \(S\) 中的起始位置分別為 \(i,j\), 且它們的前 \(k\) 個字元均相同,即
\[S[i \cdots i+k-1]=S[j \cdots j+k-1]
\]
不妨先考慮 \(S[i+k]>S[j+k]\) 的情況,我們發現起始位置下標 \(l\) 滿足 \(i\le l\le i+k\) 的字串均不能成為答案。因為對於任意一個字串 \(S_{i+p}\)(表示以 \(i+p\) 為起始位置的字串,\(p \in [0, k]\))一定存在字串 \(S_{j+p}\) 比它更優。
所以我們比較時可以跳過下標 \(l\in [i,i+k]\), 直接比較 \(S_{i+k+1}\)
時間複雜度 \(\mathcal{O}(n)\)
#include<bits/stdc++.h>
using namespace std;
int n,ans,A[300009];
int Min_show(){
int i=0,j=1,k=0;
while(i<n&&j<n&&k<n){
if(A[(i+k)%n]==A[(j+k)%n]) k++;
else{
if(A[(i+k)%n]>A[(j+k)%n])i+=k+1;
else j+=k+1;
if(i==j)i++;
k=0;
}
}
return min(i,j);
}
int main(){
cin >> n;
for(int i=0;i<n;i++)
cin >> A[i];
ans=Min_show();
for(int i=0;i<n;i++)
cout << A[(i + ans) % n] << " ";
return 0;
}