题目地址http://zju.acmclub.com/index.php?app=problem_title&id=1&problem_id=1056
输出字符串最小表示的第一个字母在原字符串的位置。
思路是:
1.预处理,复制原字符串的2倍作为新的字符串,例如,str=“abc”变成str=“abcabc”
2.取双指针p1、p2,p1初始指向新字符串的首字符,p2指向第二个字符
3.每次首先找到位移k,使str[p1+k]!=str[p2+k],并比较str[p1+k]与str[p2+k],
如果str[p1+k]>str[p2+k],更新p1+=k+1;如果p1移到了和p2相同的位置,则p1再移一位;反之则更新p2并移动p2。
输出:
1.如果k等于原字符串的长度,说明循环同构,输出min(p1,p2)
2.如果p1、p2两者中的任何一个移到了原字符串长度之外,则输出另一方即可。
python代码:
#coding=utf-8
t = input()
while t:
[n,s] = raw_input().split()
#init point
p1 = 0
p2 = 1
s = s*2
#print len(s)
while True:
k = 0
while s[p1+k]==s[p2+k] and k!=int(n):
k+=1
if k==int(n):
print min(p1,p2)
break
if s[p1+k]>s[p2+k]:
p1+=k+1
if p1==p2:p1+=1
elif s[p1+k]<s[p2+k]:
p2+=k+1
if p1==p2:p2+=1
if p1>=int(n):
print p2
break
if p2>=int(n):
print p1
break
t -= 1
if t==0:break
用python可能时间超限,可以考虑用c++重写
c++代码:
#include<iostream>
#include<cstring>
#define MAXN 200010
using namespace std;
int min_string(int num,char *s)
{
char str[MAXN];
int p1 = 0,p2 = 1,k;
strcpy(str,s);
strcat(s,str);
while(1)
{
k = 0;
while(s[p1+k]==s[p2+k]&&k!=num) k++;
if (k==num)return min(p1,p2);
if (s[p1+k]>s[p2+k])
{
p1+=k+1;
if(p1==p2)p1++;
}
else if (s[p1+k]<s[p2+k])
{
p2+=k+1;
if(p1==p2)p2++;
}
if (p1>=num) return p2;
if (p2>=num) return p1;
}
return -1;
}
int main()
{
int t,n;
cin>>t;
char s[MAXN];
while(t--)
{
cin>>n>>s;
cout<<min_string(n,s)<<endl;
}
return 0;
}
ps:数组MAXN尽量要开的大一点,开小了总提示段错误~!