最小表示法

最小表示法

参考:最小表示法

目的:O(n)求出一个序列循环同构中最小的那一个(在字符串中表示为字典序最小的一个循环同构)

优化内容:i,j 分别是当前比较的起始下标,k 是已比较的个数。当前假设\(A_{i+k}>B_{j+k}\),那么对于\(i+p(i\le i+p\le i+k)\)起始的字符串,\(S_{j+p}\)一定比它更优,所以这一段可以直接跳过。

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
int a[maxn];

int main(){
    int n;cin>>n;
    for(int i=0;i<n;++i) cin>>a[i];
    int k=0,i=0,j=1;
    while(k<n&&i<n&&j<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;
        }
    }
    int op=min(i,j);
    for(i=0;i<n;++i)
        cout<<a[(op+i)%n]<<" \n"[i==n-1];
}
posted @ 2020-08-16 16:44  caoanda  阅读(202)  评论(0编辑  收藏  举报