最小表示法
感觉这是一个很冷门的算法?
遇到的题不多,但是很有趣。
什么是最小表示法
用来求一个字符串或数列,循环得到的串或数列,字典序最小的是哪个。
如何求最小表示法
- 定义两个指针 \(i\) 和 \(j\),初始时指向 \(0\) 和 \(1\)。
- 维护一个 \(k\),表示 \(i\) 开头的子串和 \(j\) 开头的子串,现在的前 \(k-1\) 位是相同的。
- 比较第 \(k\) 位,如果依然相等就 \(k++\)。
- 否则假设更大的那个子串,从它的头指针位置到现在的第 \(k\) 位开头的子串,一定也大于更小的那个子串从它的头指针位置到现在的第 \(k\) 位开头的子串,所以大的那个跳到现在的第 \(k+1\) 位,并重新匹配。(有点像绕口令.....)
- 如果指针跳的时候 \(i=j\) 了,那么令其中一个再向后跳。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int n,p,a[N];
int main()
{scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d",&a[i]);int i=0,j=1,k=0;while(i<n&&j<n&&k<n){if(a[(i+k)%n]>a[(j+k)%n])i=i+k+1,k=0;else if(a[(i+k)%n]<a[(j+k)%n])j=j+k+1,k=0;else k++;if(i==j)i++;}p=min(i,j);for(int i=0;i<n;i++)printf("%d ",a[(p+i)%n]);return 0;
}