1.题目链接:https://vjudge.net/contest/365138#problem/B
解法一:直接暴力利用string的compare和substr
(这样竟然也能过,哭了)
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int main()
{
int t;
cin>>t;
string s;
while(t--)
{
cin>>s;
int len=s.size();
s+=s;
string mins=s.substr(0,len);
int minpos=0;
for(int i=1;i<len;i++)
{
string temp=s.substr(i,len);
if(temp.compare(mins)<0)
{
mins=temp;
minpos=i;
}
}
printf("%d\n",minpos+1);
}
return 0;
}
解法二:最小表示法
用于求一个字符串首尾相连时的最小字典序
模版:
i=0,j=1;
while(i<=n&&j<=n) {
for(k=0;k<n&&w[i+k]==w[j+k];k++);
if(k==n) break;
if(w[i+k]>w[j+k]) {
i+=k+1; if(i==j) i++;
}else {
j+=k+1; if(i==j) j++;
}
}
i=min(i,j);
意思就是从i=0、j=1开始,k=0
①如果s[i+k]s[j+k],则k++;
②如果s[i+k]>s[j+k],则i=i+k+1;若ij,则i++;
③如果s[i+k]<s[j+k],则j=j+k+1,若i==j,则j++;
先来解释一下②,abcdabcae字符串为例,
i=0,j=4,k=0开始,当k=0,1,2时,s[i+k]==s[j+k],当k=3时,s[i+k]=‘d’,s[j+k]=‘a’,s[i+k]>s[j+k],此时要让i=i+k+1。那我们直接证明在i到i+k之间不存在最小字典序的字符串就好,取中间一点为i+p,因为s[i+k]>s[j+k],s[i+p]到s[i+k-1]与s[j+p]到s[j+k-1]相同,那么i+p到i+k字典序一定是大于j+p到j+k的,所以可以直接让i跳到i+k+1处。
③的证明也同理。
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int main()
{
int t;
cin>>t;
string s;
while(t--)
{
cin>>s;
int len=s.size();
s+=s;
int i=0,j=1,k=0;
while(i<len&&j<len)
{
k=0;
while(k<len&&s[i+k]==s[j+k]) k++;
if(k==len)
break;
if(s[i+k]>s[j+k])
{
i=i+k+1;
if(i==j)
i++;
}
else
{
j=j+k+1;
if(i==j)
j++;
}
}
cout<<min(i,j)+1<<endl;
}
return 0;
}
2.HDU4162http://acm.hdu.edu.cn/showproblem.php?pid=4162
难在题意理解,就是为了便于记录一个图形的旋转等操作,将字符串表示成差分形式,及s[i]=(s[i+1]-s[i]+8)%8,然后利用最小表示法找最小字典序即可
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
string s;
int change[610000];
int len;
int MinimumRepresentation()
{
int i=0,j=1;
int k;
while(i<len&&j<len)
{
k=0;
while(k<len&&change[i+k]==change[j+k]) k++;
if(k==len)
break;
if(change[i+k]>change[j+k])
{
i=i+k+1;
if(i==j)
i++;
}
else
{
j=j+k+1;
if(i==j)
j++;
}
}
return min(i,j);
}
int main()
{
while(cin>>s)
{
len=s.size();
s+=s;
for(int i=0;i<2*len-1;i++)
{
change[i]=(s[i+1]-s[i]+8)%8;
}
change[2*len-1]=change[len-1];
int pos=MinimumRepresentation();
for(int i=0;i<len;i++)
printf("%d",change[i+pos]);
printf("\n");
}
return 0;
}