【知识】字符串 最小表示法

问题描述:

最小表示法是字符串 \(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;
}
posted @ 2024-12-05 22:34  Star_F  阅读(12)  评论(0编辑  收藏  举报