放到SAM上统计right集合大小然后就完了
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=2e5+5;
int n,k;
char s[N];
namespace SAM{
int ch[N][26],fa[N],l[N],last,tot,siz[N];
inline void ins(int c){
int p=last,np=++tot;last=np;l[np]=l[p]+1;siz[np]=1;
for(;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=1;
else{
int q=ch[p][c];
if(l[q]==l[p]+1) fa[np]=q;
else{
int nq=++tot;l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];fa[q]=fa[np]=nq;
for(;p && ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
}
}
int c[N],rk[N],pre[N];
inline void getright(){
for(int i=1;i<=tot;i++) ++c[l[i]];
for(int i=1;i<=tot;i++) c[i]+=c[i-1];
for(int i=tot;i;i--) rk[c[l[i]]--]=i;
for(int i=tot;i;i--){
int u=rk[i];
siz[fa[u]]+=siz[u];
if(siz[u]==k) ++pre[l[fa[u]]+1],--pre[l[u]+1];
}
}
inline void getans(){
int ans=0,mx=0;
for(int i=1;i<=tot;i++){
pre[i]+=pre[i-1];
if(pre[i]>=mx && pre[i]!=0) ans=i,mx=pre[i];
}
if(!ans) puts("-1");
else cout<<ans<<"\n";
}
inline void init(){
memset(ch,0,sizeof(ch));
memset(c,0,sizeof(c));
memset(siz,0,sizeof(siz));
memset(pre,0,sizeof(pre));
last=tot=1;
}
inline void work(){
init();
scanf("%s",s+1);
k=read();n=strlen(s+1);
for(int i=1;i<=n;i++) ins(s[i]-'a');
getright();
getans();
}
}
int main(){
int t=read();
while(t--) SAM::work();
return 0;
}