题目:click
看插头dp看到的记录一下。
问一个循环的字符串,也就是首尾相接的环形字符串的字典序最小的操作数,每次可以把前面的一个字符移动到尾部。
定义两个指针变量i=0,j=1,k=0表示以i或者j开始长度为k的字符串。
1:去比较s[(i+k)%n]与s[(j+k)%n]的大小
2:相等的话k++;
3:A:如果s[(i+k)%n]大的话,i+=k+1 相当于右移,j=i+1,k=0重新开始
B:否则,将j移动。
所有的终止条件i<n&&j<n&&k<n,相当于跑了一遍字符串的环每个字符串作为开头的情况。
同理最大表示法的话,就是s[(i+k)%n]大的话 j+=k+1 否则i+=k+1因为i小需要放走。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
char s[10100];
int solve()
{
int n=strlen(s);
int i=0,j=1,k=0;
while(i<n&&j<n&&k<n)
{
int temp=s[(i+k)%n]-s[(j+k)%n];
if(!temp)
{
k++;
continue;
}
if(temp>0)
i+=k+1;
else
j+=k+1;
if(i==j)
j=i+1;
k=0;
}
return min(i,j)+1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int i,j,k;
scanf("%s",s);
printf("%d\n",solve());
}
return 0;
}