https://ac.nowcoder.com/acm/contest/5669/I
题意:
就是求每个前缀的最小后缀,答案是用最小位置算
解析:
先lyndon分解,显然最后的lyndon串的字典序最小。
在最后lyndon串内部,用KMP判断。
当后缀等于前缀时,即当 时,pre为最小字典序。
这个用KMP求,但是KMP求的是最长,我们求的是最短( KMP得到aa,而实际最小是a)。这个处理办法是对aa再次跳fail,这个过程用记忆化加速。
代码:
/*
* Author : Jk_Chen
* Date : 2020-07-21-15.03.56
*/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL mod=1e9+7;
const int maxn=1e6+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/
vector<int>Pos;
void deal(char *x,int len){
int i=0;
while(i<len){
int j=i,k=i+1;
while(k<len&&x[j]<=x[k]){
if(x[j]==x[k])
j++;
else
j=i;
k++;
}
while(i<=j){
i+=k-j;
Pos.push_back(i);
}
}
}
int fail[maxn];
void KMP(char *x,int *fail,int L,int R){
// int i=L,j=-1;
// fail[0]=-1;
// while(i<=R){
// while(j!=-1&&x[i]!=x[j]) j=fail[j];
// fail[++i]=++j;
// if(x[i]==x[j]) fail[i]=fail[j];
// }
fail[L]=-1,fail[L+1]=L;
int i=L+1,j=L;
while(i<=R&&j<=R){
if(j==-1||x[i]==x[j]){
if(j==-1)
fail[++i]=j=L;
else
fail[++i]=++j;
}
else j=fail[j];
}
}
char x[maxn];
LL ans[maxn];
// every substring's endpos , index begin at 1
int F[maxn];
int Find(int p,int L){
if(F[p]!=-1)return F[p];
if(fail[p+1]>L){
int len=Find(fail[p+1]-1,L);
if(len==inf)
return F[p]=fail[p+1]-L;
else
return F[p]=len;
}
else{
return F[p]=inf;
}
}
int main(){
int _=rd;
while(_--){
Pos.clear();
scanf("%s",x);
int len=strlen(x);
rep(i,0,len)F[i]=-1;
deal(x,len);
int L=0,R;
for(int i=0;i<Pos.size();i++){
R=Pos[i]-1;
#ifdef TEST
test(L,R);
#endif // TEST
KMP(x,fail,L,R);
rep(j,L,R){
int res=Find(j,L);
if(res!=inf)
ans[j]=j-res+1;
else
ans[j]=L;
}
L=Pos[i];
}
LL A=0,B=1;
rep(i,0,len-1){
#ifdef TEST
test(ans[i]+1);
#endif // TEST
A=(A+B*ans[i]+B)%mod;
B=B*1112%mod;
}
printf("%lld\n",A);
}
return 0;
}
/*
100
abababbacbbacbaccbaaacaabcac
4
bbaabaaab
baacbaacb
aabaabaabc
abcabcabc
*/