最小表示法
Summary
最小表示法求字符串所有循环同构中字典序最小者的起始位置。维护两个指针 i、j 与它们的公共前缀长度 k:逐位比较两个起点后移 k 位的字符,相等则 k 加一;一旦某侧字符更大,则以该侧起点开头的后续 k+1 个位置都不可能最优,直接令指针跳过 k+1、重置 k 从头再比。每个位置至多被跳过一次,时间复杂度为 O(n)。实现输出以最小表示起点展开的循环串。
参考资料
简介
最小表示法(Minimum String Rotation)用于求字符串 所有循环同构中字典序最小的那个的起始位置。
维护两个指针 (初始为 )和公共前缀长度 :每次比较 与 ,相同则 加一;若 ,则以 为起点的后续 个位置均非最优,直接跳过令 ,同理对称处理 。时间复杂度为 。
实现
#include <bits/stdc++.h>
using namespace std;
int minimal(string s)
{
int n=s.size();
int i=0,j=1,k=0;
while(k<n&&i<n&&j<n)
{
if(s[(i+k)%n]==s[(j+k)%n])
{
k++;
}
else
{
s[(i+k)%n]>s[(j+k)%n]?i=i+k+1:j=j+k+1;
if(i==j)i++;
k=0;
}
}
return min(i,j);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s;
cin>>s;
int p=minimal(s);
int n=s.size();
for(int i=0;i<n;i++)cout<<s[(p+i)%n];
cout<<'\n';
return 0;
}