【知識】字串 最小表示法

Star_F發表於2024-12-05

問題描述:

最小表示法是字串 \(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;
}

相關文章