<img>標籤
阿新 • • 發佈:2020-11-27
今天 LJ 課上講了最小表示法。感覺很好理解。
決定寫一篇部落格,自己梳理一下。
最小表示法是
我們可以定義三個指標 \(i,j,k\) 。
其中 \(i=0,j=1,k=0\) ,\(k\) 表示以 \(S_i\) 開頭的字串和以 \(S_j\) 開頭的字串的前 \(k\) 個字元相同。
然後我們列舉 \(k\) 。
當 \(S_{i+k}=S_{j+k}\) 則繼續。
當 \(S_{i+k}>S_{j+k}\) 則表明 \(S_{[i,i+k]}\) 肯定不可以作為目標字串的開頭。
當 \(S_{i+k}<S_{j+k}\)
當 \(i=j\) 時,令 \(j+1\) 。
後面三種情況都要使 \(k\) 歸 \(0\) 。
程式碼很好寫
#include<bits/stdc++.h> #define FOR(i,j,k) for(int i=(j);i<=(k);i++) using namespace std; int n; int a[300005]; inline int read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } inline int Min() { int i=0,j=1,k=0; while(i<n&&j<n&&k<n) { int t=a[(i+k)%n]-a[(j+k)%n]; if(!t) k++; else { if(a[(i+k)%n]>a[(j+k)%n]) i+=k+1; else j+=k+1; if(i==j) j++; k=0; } } return min(i,j); } int main() { n=read(); for(int i=0;i<n;i++) a[i]=read(); int ans=Min(); for(int i=0;i<n;i++) printf("%d ",a[(i+ans)%n]); return 0; }
當然他也可以用來判斷兩個字串不計順序是否本質相同。詳細可以參見這個PPT