bzoj3230 相似子串 SA lcp 二分

2021-08-04 21:10:44 字數 1448 閱讀 5471

首先用字尾陣列處理出h陣列。因為要問子串的排名,所以我們再記乙個陣列num[i],表示前i個字尾有幾個本質不同的子串。然後我們用二分查詢就可以找到排序後的第i個子串是誰了。然後就是求一下lcp了。。還有反過來的lcp。。算清角標就好了。。還有很坑的一點:可能有超過int範圍個實質不同的字串=,=.

#include 

#include

#include

using

namespace

std;

#define n 100010

#define ll long long

#define inf 0x7f7f7f7f

int n,q,log[n];

inline

int min(int x,int y)

inline ll read()

while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();

return x*f;

}struct sa

}k=0;

for(int i=1;i<=n;++i)

if(i==1||h[rank[i-1]]<=1) k=0;

if(k) --k;

while(s[i+k]==s[sa[rank[i]-1]+k]) ++k;

h[rank[i]]=k;

}for(int i=1;i<=n;++i)

for(int i=1;i<=log[n];++i)

for(int j=1;j<=n;++j)

if(j+(1

<1)<=n) st[j][i]=min(st[j][i-1],st[j+(1

<1)][i-1]);

}int lcp(int l,int r)

}a,b;

int main()

id=lower_bound(a.num+1,a.num+n+1,l)-a.num;

sta1=a.sa[id];ed1=sta1+a.h[id]+l-a.num[id-1]-1;

id=lower_bound(a.num+1,a.num+n+1,r)-a.num;

sta2=a.sa[id];ed2=sta2+a.h[id]+r-a.num[id-1]-1;

a= sta1==sta2?inf:a.lcp(a.rank[sta1],a.rank[sta2]);

a=min(a,min(ed1-sta1+1,ed2-sta2+1));ans+=(ll)a*a;

b= n-ed1+1==n-ed2+1?inf:b.lcp(b.rank[n-ed1+1],b.rank[n-ed2+1]);

b=min(b,min(ed1-sta1+1,ed2-sta2+1));ans+=(ll)b*b;

printf("%lld\n",ans);

}return

0;}

bzoj 3230 相似子串

time limit 20 sec memory limit 128 mb submit 1767 solved 438 submit status discuss 輸入第1行,包含3個整數n,q。q代表詢問組數。第2行是字串s。接下來q行,每行兩個整數i和j。1 i j 輸出共q行,每行乙個數表示...

BZOJ 3230 相似子串

給定乙個長度為 n 的字串以及 q 組查詢,每組查詢給定 a 和 b 求在所有本質不同子串中排名第 a 和第 b 的串的最長公共字首與最長公共字尾的平方和.n,q le 1 times 10 5 字尾陣列板子題.麻麻我終於會用字尾陣列辣 本來想接著用sam的.但是發現多組查詢排名為 k 的本質不同子...

BZOJ3230 相似子串

3230 相似子串 time limit 20 sec memory limit 128 mb submit 913 solved 223 submit status description input 輸入第1行,包含3個整數n,q。q代表詢問組數。第2行是字串s。接下來q行,每行兩個整數i和j。...