P13270 【模板】最小表示法
P13270 【模板】最小表示法
大意
字符串 \(s\) 的最小表示为与 \(s\) 循环同构的所有字符串中字典序最小的字符串。
思路
最小表示法的意思,顾名思义就是一个字符串 \(S\), 你要求出他的最小的表示方式,表示的方式如下:就是把 \(S\) 的循环同构中的字符串中的字典序最小的表示方法求出来。
然后,我们考虑断环成链,然后每次去比较每一个位置的字符串:
枚举 \(i\) 和 \(j\),然后枚举 \(k\),比较 \(s[i + k]\) 和 \(s[j + k]\) 位置的大小关系,如果是 \(s[i + k] > s[j + k]\) 的话就让 \(i++\),否则 $ j++$。
这样的复杂度是 \(O(n^2)\) 的,我们考虑优化。
如果比较到当前的 \(S[i + k] > S[j + k]\) 的话,那么,就是对于从 \(i\) ~ \(i + k\) 的位置,都并不优,因为都有 \(p \in [i + 1, k]\) 的部分,在 \(p = k\) 的地方都有 \(S[i + p] > s[j + p]\) 。因此,当到 \(k\) 的地方时,无论是大于或是小于,从 \(i\) ~ \(i + k\) 或 \(j\) ~ \(j + k\) 的部分一定可以跳过,因此,时间复杂度为 \(O(n)\) 的。
代码
#include<iostream>
using namespace std;
const int MAXN = 1e7 + 5;
int n;
char s[MAXN];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
cin >> (s + 1);
int k = 0, i = 1, j = 2;
while(k <= n && i <= n && j <= n){
if(s[(i + k) % n + 1] == s[(j + k) % n + 1]){
k ++;
}
else{
if(s[(i + k) % n + 1] > s[(j + k) % n + 1]){
i = i + k + 1;
}
else{
j = j + k + 1;
}
k = 0;
if(i == j) j ++;
}
}
for(int p = min(i, j);p <= n + min(i, j) - 1;p ++){
cout << s[(p % n) + 1];
}
return 0;
}
本文来自一名高中生,作者:To_Carpe_Diem

浙公网安备 33010602011771号