BZOJ3230 相似子串

2022-05-12 01:10:42 字數 2734 閱讀 8331

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。(1≤i≤j)。

output

輸出共q行,每行乙個數表示每組詢問的答案。如果不存在第i個子串或第j個子串,則輸出-1。

sample input

5 3ababa

3 55 9

8 10

sample output

-1hint

樣例解釋

第1組詢問:兩個子串是「aba」,「ababa」。f = 32 + 32 = 18。

第2組詢問:兩個子串是「ababa」,「baba」。f = 02 + 42 = 16。

第3組詢問:不存在第10個子串。輸出-1。

資料範圍

n≤100000,q≤100000,字串只由小寫字母'a'~'z'組成

source

字尾陣列+二分+rmq

題解:字典序第i?我們給每個排名為i字尾i乙個ed[i]表示截止到排名i,一共有多少個本質不同的子串,然後在ed陣列上lower_bound就可以找到子串的左端點,然後就知道右端點了。

然後求lcp?和lcs?(longest common suffix?)

兩個字尾陣列可以o(nlogn)預處理,o(1)查詢。

hash可以o(n)預處理,o(logn)查詢。

作為蒟蒻我寫了後一種。。。

**:

1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include

10 #include11 #include

12#define inf 1000000000

13#define maxn 150000+5

14#define maxm 500+100

15#define eps 1e-10

16#define ll long long

17#define ull unsigned long long

18#define pa pair19

#define for0(i,n) for(int i=0;i<=(n);i++)

20#define for1(i,n) for(int i=1;i<=(n);i++)

21#define for2(i,x,y) for(int i=(x);i<=(y);i++)

22#define for3(i,x,y) for(int i=(x);i>=(y);i--)

23#define mod 1000000007

24#define base 13131

25using

namespace

std;

26inline ll read()

2730

while(ch>='

0'&&ch<='9')

31return x*f;32}

33int

n,q,s[maxn],t[maxn],t2[maxn],c[maxn],sa[maxn],rk[maxn],h[maxn];

34ll ed[maxn];

35ull hash[maxn],mi[maxn];

36void getsa(int

m)37

57 for1(i,n)rk[sa[i]]=i;

58for(int i=0,k=0,j;ik)

59for(k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);60}

61void

gethash()

6267 inline ull get(int x,int y)

68int

main()

6974 s[n]=0

;75 getsa(26

);76 for1(i,n)ed[i]=n-sa[i]-h[i];

77 for1(i,n)ed[i]+=ed[i-1

];78

gethash();

79while(q--)

8083 ll t=lower_bound(ed+1,ed+n+1,x)-ed,l1=sa[t],r1=sa[t]+h[t]+x-ed[t-1]-1

;84 t=lower_bound(ed+1,ed+n+1,y)-ed;ll l2=sa[t],r2=sa[t]+h[t]+y-ed[t-1]-1;85

int l=0,r=min(r1-l1+1,r2-l2+1

);86

while(l<=r)

8791 ll ans=(ll)r*(ll)r;

92 l=0,r=min(r1-l1+1,r2-l2+1

);93

while(l<=r)

9498 ans+=(ll)r*(ll)r;

99 printf("

%lld\n

",ans);

100}

101return0;

102 }

view code

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 相似子串 SA lcp 二分

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