简要题意:
给一个串,询问有多少个区间可以由某一个串重复 次得到。
题解:
首先很容易发现就是询问有多少个子串有 的循环节。
也就是说要有 的 border。
也就是求由多少对 ,满足
直接建立SAM然后DSU on tree 即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int N=3e5+7;
int n,k;
char s[N];
namespace SAM{
cs int N=::N<<1|1;
int fa[N],len[N],nw;
void init(){
for(int re i=1;i<=n;++i)
len[i]=i;nw=n+1;
}void ins(int i,int c){
static int son[N][26];
int cur=i,p=(i-1)?(i-1):(n+1);
for(;p&&!son[p][c];p=fa[p])
son[p][c]=cur;
if(!p)fa[cur]=n+1;
else {
int q=son[p][c];
if(len[q]==len[p]+1)fa[cur]=q;
else {
int nq=++nw,q=son[p][c];
memcpy(son[nq],son[q],sizeof son[q]);
len[nq]=len[p]+1,fa[nq]=fa[q];fa[q]=fa[cur]=nq;
for(;p&&son[p][c]==q;p=fa[p])
son[p][c]=nq;
}
}
}
int bin[N],nd[N];
void radix_sort(){
for(int re i=1;i<=nw;++i)++bin[len[i]];
for(int re i=1;i<=n;++i)bin[i]+=bin[i-1];
for(int re i=nw;i;--i)nd[bin[len[i]]--]=i;
}
std::vector<int> q[N];
int el[N],nx[N];
int sz[N],son[N],top[N];
void init_fail(){
for(int re i=nw;i;--i){
int u=nd[i];sz[fa[u]]+=++sz[u];
if(sz[u]>sz[son[fa[u]]])son[fa[u]]=u;
if(u!=n+1)nx[u]=el[fa[u]],el[fa[u]]=u;
}for(int re i=1;i<=nw;++i){
int u=nd[i];if(!top[u])top[u]=u;
if(son[u])top[son[u]]=top[u];
}for(int i=1;i<=n;++i){
int u=i;while(u){
q[top[u]].push_back(i);
u=fa[top[u]];
}
}
}
int tr[::N],st[::N],tp;
void add(int p){
st[++tp]=p;
for(;p<=n;p+=p&-p)++tr[p];
}int qy(int p){
int r=0;for(;p;p^=p&-p)r+=tr[p];
return r;
}void clr(){
while(tp){
int p=st[tp--];
for(;p<=n;p+=p&-p)tr[p]=0;
}
}int qy(int l,int r){
return qy(std::min(r,n))-qy(std::max(l,1)-1);
}
int rg;ll ans;
void dfs(int u){
for(int re v=el[u];v;v=nx[v])
if(v!=son[u])dfs(v),clr();
if(son[u])dfs(son[u]);rg=len[u]/k;
for(int re v=el[u];v;v=nx[v])
if(v!=son[u]){
for(int re w:q[v])
ans+=qy(w-rg,w+rg);
for(int re w:q[v])add(w);
}
if(u<=n)
ans+=qy(u-rg,u+rg),add(u);
}
}//namespace SAM
void Main(){
scanf("%d%d",&n,&k);--k;
scanf("%s",s+1);SAM::init();
for(int re i=1;i<=n;++i)
SAM::ins(i,s[i]-'a');
SAM::radix_sort();SAM::init_fail();
SAM::dfs(n+1);cout<<SAM::ans<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("sutoringu.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
freopen("sutoringu.in","r",stdin);
freopen("sutoringu.out","w",stdout);
#endif
#endif
}signed main(){file();Main();return 0;}
来源:CSDN
作者:zxyoi_dreamer
链接:https://blog.csdn.net/zxyoi_dreamer/article/details/104576108