最小表示法
最小表示法:
定义:
就是一个字符串的最小表示形式
解决过程:
将原字符串 \(s\) 复制一遍放在串尾
s=s+s;
设 \(i=0\) 指向字符串头,\(j=i+1\)。
int i=0,j=1,len=s.size()/2;
再设一个偏移量 \(k=0\) ,如果 \(s[i+k]==s[j+k]\),\(k++\)
int k=0;
while(s[i+k]==s[j+k]) k++;
不相等让大的加上 \(k+1\)
因为在 \([i/j,i/j+k]\) 间都有对应的另一个指针指向的字符串比它小,所以一定不是最小表示。
if(s[i+k]>s[j+k]) i=i+(k+1);
else j=j+k+1;
如果 \(k \geq len\) 则说明字符串每个位置由相同字母组成,应该是满足条件的最小表示,直接跳出,转移到求最小值。
if(k>=len) break;
如果 \(i=j\) 则其中一个加 \(1\) 即可,没有实际影响。
if(i==j) i++;
最后求最小值,返回在原串内比较小的坐标开头
return min(i,j);
时间复杂度为 \(O(n)\)
代码:
int get_min(string s){
s=s+s;
int i=0,j=1,len=s.size()/2;
while(i<len && j<len){
int k=0;
while(s[i+k]==s[j+k]) k++;
if(k>=len) break;
if(s[i+k]>s[j+k]) i=i+k+1;
else j=j+k+1;
if(i==j) i++;
}
return min(i,j);
}
例题:
P1709 [USACO5.5]隐藏口令Hidden Password
这题就是模板题,但是注意读入时,题目给的数据有换行!!!
#include<bits/stdc++.h>
using namespace std;
int n;
char s[10000005];
int minstring(){
for(int i=0;i<n;i++) s[i+n]=s[i];
int len=strlen(s)/2;
int i=0,j=1;
while(i<len&&j<len){
int k=0;
while(s[i+k]==s[j+k]) k++;
if(k>=len) break;
if(s[i+k]>s[j+k]) i=i+k+1;
else j=j+k+1;
if(i==j) j++;
}
return min(i,j);
}
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>s[i];
int ans=minstring();
cout<<ans<<endl;
system("pause");
return 0;
}
不关注的有难了😠😠😠https://b23.tv/hoXKV9