Description
给你一个长度为 \(n\) 的数组 \(a[]\),在差分数组里面找 \(ABA\) 的形式,这里 \(B\) 的长度要求为 \(m\),找这样的连续段的个数。
Solution
枚举每种 \(A\) 长度 \(i\),则每隔 \(i\) 设置一个关键点,在这些关键点上求出 LCS 和 LCP,则我们会得到一段合法的区间
于是我们得到这段这个关键点对答案的贡献为 \(lenlcp + lenlcs -i\)
由于在 \(len(A)=i\) 的情况下,有且仅有对 \(j\) 这个关键点的统计中,\(A_{left}\) 是跨过 \(j\) 的,因此统计不重不漏
为了求 LCP 和 LCS,对差分序列正反各建 SAM,用 ST 表维护后缀树支持 LCA 询问,根据调和级数,时间复杂度为 \(O(n \log n)\)
(其实明显应该写 SA 嘛,为了尝试用 SAM 搞 LCP 才写的)
#include
using namespace std;
const int N = 600005;
const int lgn = 19;
const int dbg = 0;
struct lcasolver
{
int rt,st[N][lgn],dep[N],dis[N],vis[N],ind,lg2[N],s[N],bg[N],ed[N];
vector g[N];
lcasolver()
{
memset(st,0,sizeof st);
memset(dep,0,sizeof dep);
memset(vis,0,sizeof vis);
memset(s,0,sizeof s);
memset(bg,0,sizeof bg);
memset(ed,0,sizeof ed);
}
void dfs(int p)
{
vis[p]=1;
s[++ind]=p;
bg[p]=ind;
for(int q:g[p])
{
if(vis[q]==0)
{
dep[q]=dep[p]+1;
dfs(q);
s[++ind]=p;
}
}
ed[p]=ind;
}
int lca(int p,int q)
{
p=bg[p];
q=bg[q];
if(p>q) swap(p,q);
int l=lg2[q-p+1];
int x=st[p][l];
int y=st[q-(1< ch[N];
int t[N], a[N], cnt[N], f[N], ep[N], tot;
void clear()
{
ind = last = 1;
tot = 0;
memset(len,0,sizeof len);
memset(fa,0,sizeof fa);
memset(t,0,sizeof t);
memset(a,0,sizeof a);
memset(cnt,0,sizeof cnt);
memset(f,0,sizeof f);
for(int i=1; i<=ind; i++) ch[i].clear();
}
SAM()
{
clear();
}
inline void extend(int id)
{
int cur = (++ ind), p;
len[cur] = len[last] + 1;
cnt[cur] = 1;
for (p = last; p && !ch[p][id]; p = fa[p]) ch[p][id] = cur;
if (!p) fa[cur] = 1;
else
{
int q = ch[p][id];
if (len[q] == len[p] + 1) fa[cur] = q;
else
{
int tmp = (++ ind);
len[tmp] = len[p] + 1;
ch[tmp] = ch[q];
fa[tmp] = fa[q];
for (; p && ch[p][id] == q; p = fa[p]) ch[p][id] = tmp;
fa[cur] = fa[q] = tmp;
}
}
last = cur;
ep[++tot] = last;
}
void calcEndpos()
{
memset(t, 0, sizeof t);
for(int i=1; i<=ind; i++) t[len[i]]++;
for(int i=1; i<=ind; i++) t[i]+=t[i-1];
for(int i=1; i<=ind; i++) a[t[len[i]]--]=i;
for(int i=ind; i>=1; --i) cnt[fa[a[i]]]+=cnt[a[i]];
cnt[1] = 0;
}
void solve(lcasolver& tr)
{
calcEndpos();
for(int i=1;i<=ind;i++)
{
if(fa[i]!=0) tr.make(fa[i],i);
}
tr.solve();
}
int query(lcasolver& tr, int p, int q)
{
int l = tr.lca(ep[p],ep[q]);
return len[l];
}
} sam1,sam2;
int n,m,a[N],b[N];
int getlcs(int p,int q)
{
return sam1.query(lca1,p,q);
}
int getlcp(int p,int q)
{
return sam2.query(lca2,n-p,n-q);
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=0;i>a[i], b[i]=a[i]-a[i-1];
for(int i=1;i=n) break;
int lcs=getlcs(p,q), lcp=getlcp(p,q);
lcs=min(lcs,i);
lcp=min(lcp,i);
if(lcs+lcp-1>=i)
{
ans+=lcs+lcp-i;
}
}
}
cout<