有一个很显然的结论,一个周期串一定是一个本原平方串,否则字典序不优。所以先进行一次Lyndon分解,求出以每个字符开头的最短本原平方串,最后求前缀最小串即可。中途求字符串LCS、LCP以及比大小都可以用二分哈希来实现。
时间复杂度
O
(
n
log
2
n
+
m
)
O(n \log_2n +m)
O(nlog2n+m),空间复杂度
O
(
n
)
O(n)
O(n)
#include<stdio.h>
#include<string.h>
#define R register int
#define C const int
#define I inline
#define N 500002
#define P 1000000009
I void Min(int&x,C y){
if(x>y){
x=y;
}
}
char s[N];
int h[N],pw[N],rt[N],len[N],ansl[N],ansr[N],st[N],lazy[2000000];
I int GetHash(int l,int r){
int t=h[r]-(long long)h[l-1]*pw[r-l+1]%P;
return t<0?t+P:t;
}
I int GetLCP(int x,int y,int&n){
if(s[x]!=s[y]){
return 0;
}
int l=0,ans=0,mid,r=n-(x>y?x:y);
while(l<=r){
mid=l+r>>1;
if(GetHash(x,x+mid)==GetHash(y,y+mid)){
ans=mid;
l=mid+1;
}else{
r=mid-1;
}
}
return ans+1;
}
I int GetLCS(int x,int y){
if(s[x]!=s[y]){
return 0;
}
int l=0,ans=0,mid,r=(x<y?x:y)-1;
while(l<=r){
mid=l+r>>1;
if(GetHash(x-mid,x)==GetHash(y-mid,y)){
ans=mid;
l=mid+1;
}else{
r=mid-1;
}
}
return ans+1;
}
I bool Compare(int l1,int r1,int l2,int r2,int&n){
int len=GetLCP(l1,l2,n);
if(len>r1-l1||len>r2-l2){
return r1-l1<r2-l2;
}
return s[l1+len]<s[l2+len];
}
I void Init(int p,int lf,int rt){
lazy[p]=N;
if(lf!=rt){
Init(p<<1,lf,lf+rt>>1);
Init(p<<1|1,lf+rt+2>>1,rt);
}
}
I void Modify(int p,int lf,int rt,C l,C r,C d){
if(l<=lf&&rt<=r){
Min(lazy[p],d);
}else{
int mid=lf+rt>>1;
if(l<=mid){
Modify(p<<1,lf,mid,l,r,d);
}
if(r>mid){
Modify(p<<1|1,mid+1,rt,l,r,d);
}
}
}
I void Release(int p,int lf,int rt,int pre){
Min(pre,lazy[p]);
if(lf==rt){
len[lf]=pre;
}else{
Release(p<<1,lf,lf+rt>>1,pre);
Release(p<<1|1,lf+rt+2>>1,rt,pre);
}
}
I void GetRuns(int&n){
int Top=0,r,p,cl,cr;
st[Top]=n+1;
for(R i=n;i!=0;i--){
while(Top!=0&&Compare(i,st[Top]-1,st[Top],st[Top-1]-1,n)==true){
Top--;
}
r=st[Top]-1;
p=r-i+1;
cl=i-GetLCS(i-1,r);
cr=r+GetLCP(i,r+1,n);
if(cr-cl+1>=p<<1){
Modify(1,1,n,cl,cr-(p<<1)+1,p);
}
Top++;
st[Top]=i;
}
}
int main(){
pw[0]=1;
scanf("%s",s+1);
int n=strlen(s+1);
Init(1,1,n);
for(R i=1;i<=n;i++){
pw[i]=29ll*pw[i-1]%P;
h[i]=(29ll*h[i-1]+s[i]-'a')%P;
}
GetRuns(n);
for(R i=1;i<=n;i++){
s[i]='a'+'z'-s[i];
}
GetRuns(n);
for(R i=1;i<=n;i++){
s[i]='a'+'z'-s[i];
}
Release(1,1,n,N);
for(R i=1;i<=n;i++){
if(len[i]==N){
ansl[i]=ansl[i-1];
ansr[i]=ansr[i-1];
}else{
ansl[i]=i;
ansr[i]=i+(len[i]<<1)-1;
if(ansl[i-1]!=0&&Compare(i,ansr[i],ansl[i-1],ansr[i-1],n)==false){
ansl[i]=ansl[i-1];
ansr[i]=ansr[i-1];
}
}
}
scanf("%d",&n);
for(R i=n;i!=0;i--){
scanf("%d",&n);
if(ansl[n]==0){
puts("-1");
}else{
printf("%d %d\n",ansl[n],ansr[n]);
}
}
return 0;
}