题意:给出一个字符串,依次左移一个单位形成一堆字符串,求其字典序最小和最大的字符串需要左移多少位,以及一共有几个这样的字符串。
题目分析:首先可以确定两个字符串出现的次数应该相同。由于假设最小的左移m位得到最大的话,那么所有相同的最小字符串左移m位都会得到最大串。对于求解最小最大串的位置可以用最小最大表示法。
最大最小表示法:总的来说就是这道题的模板,求一个循环串字典序的最小和最大的位置。算法整体思想很简单,以最小为例如题,指针i,j分别代表比较的两个串的串首位置,这两个位置是互相更新的。当s[i+k]==s[j+k]时,k++,当s[i+k]<s[j+k]时,说明j串比i串大了,同时j+m串也一定比i+m串大(m=1,2,3。。。。k)所以j到j+k之内是不会有最小串了。把j直接更新到j+k+1。大小顺序反过来的时候同理。最大表示法也同理。最后取i与j中小的一个就是其位置。另外注意一点就是当更新位置后i和j重叠的时候为方便编码同意j++。具体看代码。
最小表示法伪代码:
最小表示法的算法思路是维护两个指针i,j。
令i=0,j=1
如果S[i] > S[j] i=j, j=i+1
如果S[i] < S[j] j++
如果S[i]==S[j] 设指针k,分别从i和j位置向下比较,直到S[i] != S[j]
如果S[i+k] > S[j+k] i=i+k
否则j++
返回i和j的小者
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
char s[1000006];
int nex[1000003];
ll len;
void getnext(){
memset(nex,0,sizeof(nex));
int i=0,j=-1;
nex[0]=-1;
while(i<=len){
if(j==-1||s[i]==s[j])nex[++i]=++j;
else j=nex[j];
}
}
//求最小字符串位置
int getmin(){
int i=0,j=1,k=0;
while(i<len&&j<len&&k<len){
int t=s[(i+k)%len]-s[(j+k)%len];
if(t==0)k++;
else {
if(t>0)i=i+k+1;
else j=j+k+1;
if(i==j)j++;
k=0;
}
}
return min(i,j);
}
//求最大字符串位置
int getmax(){
int i=0,j=1,k=0;
while(i<len&&j<len&&k<len){
int t=s[(i+k)%len]-s[(j+k)%len];
if(t==0)k++;
else {
if(t<0)i=i+k+1;
else j=j+k+1;
if(i==j)j++;
k=0;
}
}
return min(i,j);
}
int main(){
while(~scanf("%s",s)){
len=strlen(s);
int minn=getmin();
int maxn=getmax();
getnext();
ll sum=1;
if(len%(len-nex[len])==0)sum=len/(len-nex[len]);//判断循环节,具体看KMP部分
printf("%d %lld %d %lld\n",minn+1,sum,maxn+1,sum);
}
return 0;
}
// /\ | / |**、
// / \ | / | \
// / \ |/ | / _____ ____ | /
// /------\ |\ |__/ / \ \ /\ / / \ | /
// / \ | \ | / \ \ / \ / /______\ |/
// / \ | \ | \ / \ / \ / \ |
// / \ | \ | \_____/ \/ \/ \_____ |
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
// warm heart, wagging tail,and a smile just for you!
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//