http://acm.hdu.edu.cn/showproblem.php?pid=3374
之前做过一道exkmp的题,就是先求的 循环节。就是用的这个代码的方法。。
开始先用表示法来算的,然后暴力枚举超时了,就想到用循环节式一下。
用string会超时,挂载也超时
给你一个串,分别输出
字典序最小同构串的 第一个字符位置(从1开始)
出现次数
字典序最大同构串的第一个位置
出现次数
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e6+1000;
int MAXR(char s[]){
int len=strlen(s)/2;
int i=0;int j=1;int k=0;
while(i<len&&j<len){
k=0;
while(s[i+k]==s[j+k]&&k<len)k++;
if(k==len) return min(i,j);
if(s[i+k]<s[j+k]) i=max(i+k+1,j+1);
else if(s[i+k]>s[j+k]) j=max(j+k+1,i+1);
}
return min(i,j);
}
int MINR(char s[]){
//cout<<s<<"!!"<<endl;
int len=strlen(s)/2;
// cout<<len<<endl;
int i=0;int j=1;//int k=0;
while(i<len&&j<len){
int k=0;
while(s[i+k]==s[j+k]&&k<len)k++;
if(k==len) return min(i,j);
if(s[i+k]>s[j+k])
i=max(i+k+1,j+1);
else if(s[i+k]<s[j+k])
j=max(j+k+1,i+1);
}
return min(i,j);
}
int nex[maxn];
int getnext(int len,char s[]){
nex[0]=-1;
int i=0;int k=-1;
while(i<len){
if(k==-1||s[i]==s[k]){
nex[++i]=++k;
}
else
k=nex[k];
}
}
int main()
{ //ios::sync_with_stdio(false);
char s[maxn];
while(~scanf("%s",s)){
int len=strlen(s);
getnext(len,s);
int siz=len-nex[len];//计算 循环节
int kk=0;
if(!(len%siz))
kk=len/siz;
else
kk=1;
for(int i=0;i<len;i++){
s[i+len]=s[i];
}
int max1=MAXR(s);
int min1=MINR(s);
int flag1=0;
int flag2=0;
printf("%d %d %d %d\n",min1+1,kk,max1+1,kk);
}
return 0;
}