字尾陣列 NOI2016 優秀的拆分

2022-05-20 07:52:59 字數 4153 閱讀 8729

如果乙個字串可以被拆分為 aa

bb的形式,其中

a 和

b 是任意非空字串,則我們稱該字串的這種拆分是優秀的。

例如,對於字串 aabaabaa,如果令 a=

aab,

b=a,我們就找到了這個字串拆分成 aa

bb的一種方式。

乙個字串可能沒有優秀的拆分,也可能存在不止一種優秀的拆分。比如我們令 a=

a,b=

baa,也可以用 aa

bb表示出上述字串;但是,字串 abaabaa 就沒有優秀的拆分。

現在給出乙個長度為

n 的字串

s,我們需要求出,在它所有子串的所有拆分方式中,優秀拆分的總個數。這裡的子串是指字串中連續的一段。

以下事項需要注意:

出現在不同位置的相同子串,我們認為是不同的子串,它們的優秀拆分均會被記入答案。

在乙個拆分中,允許出現 a=

b。例如 cccc 存在拆分 a=

b=c。

字串本身也是它的乙個子串。

每個輸入檔案包含多組資料。輸入檔案的第一行只有乙個整數

t,表示資料的組數。保證 1≤

t≤10。

接下來

t 行,每行包含乙個僅由英文小寫字母構成的字串

s,意義如題所述。

輸出 t

行,每行包含乙個整數,表示字串

s 所有子串的所有拆分中,總共有多少個是優秀的拆分。

input

4

aabbbb

cccccc

aabaabaabaa

bbaabaababaaba

output
354

7

explanation

我們用 s[

i,j]

表示字串 s

s 第

i 個字元到第

j 個字元的子串(從

1 開始計數)。

第一組資料中,共有

3 個子串存在優秀的拆分:s[

1,4]

=aab

b,優秀的拆分為 a=

a,b=

b;s[

3,6]

=bbb

b,優秀的拆分為 a=

b,b=

b;s[1,6] = \mathtts[

1,6]

=aab

bbb,優秀的拆分為 a= \mathtta=

a,b = \mathttb=

bb。而剩下的子串不存在優秀的拆分,所以第一組資料的答案是 33。

第二組資料中,有兩類,總共 4

4 個子串存在優秀的拆分:

對於子串 s[1,4] = s[2,5] = s[3,6] = \mathrms[

1,4]

=s[2

,5]=

s[3,

6]=c

ccc,它們優秀的拆分相同,均為 a = \mathrma=

c,b = \mathrmb=

c,但由於這些子串位置不同,因此要計算

3 次;

對於子串 s[

1,6]

=ccc

ccc,它優秀的拆分有

2 種:a=

c,b=

cc和 a=c

c,b=

c,它們是相同子串的不同拆分,也都要計入答案。

所以第二組資料的答案是 3+

2=5。

第三組資料中,s[

1,8]

和 s[4

,11] 各有

2 種優秀的拆分,其中 s[

1,8]

是問題描述中的例子,所以答案是 2+

2=4。

第四組資料中,s[

1,4]

,s[6

,11],

s[7,

12],s

[2,11

],s[

1,8]

各有 1 種優秀的拆分,s[

3,14]

有 2種優秀的拆分,所以答案是 5+

2=7。

對於全部的測試點,保證 1≤

t≤10。以下對資料的限制均是對於單組輸入資料而言的,也就是說同乙個測試點下的

t 組資料均滿足限制條件。

我們假定

n 為字串

s 的長度,每個測試點的詳細資料範圍見下表:

測試點編號

n其他約束

1、2≤

300s

中所有字元全部相同

3、4≤

2000

5、6\leq 10≤10

無7、8

\leq 20≤20

9、10

\leq 30≤30

11、12

\leq 50≤50

13、14

\leq 100

≤10015≤

20016

≤30017≤

50018

≤100019≤

200020≤

30000

時間限制:

1.5s

空間限制:

512mb

ccf送80分,然後剩下的各種演算法只相差5分。

直接來看滿分演算法。

我們將aa和

bb分開看,計算乙個字元開始有多少個aa

。考場上我sb

了,考完才想到可以像【字尾陣列】[uva10829]l-gap substring

那樣做。 列舉a

的長度l

,然後把整個字串按照長度

l分段,計算si

∗l和s

(i+1

)∗l的

lcp和

lcs,如果長度加起來≥l

,就說明這裡有aa

,在相應位置計數器增加1,即cn

ti∗l

−lcs

+1,c

nti∗

l−lc

s+1…

cnti

∗l−l

cs+1

+(lc

s+lc

p−1−

l)都增加1。

然後再做一遍,這次不增加計數器了,增加可能的末尾位置的計數器的和,即an

s+=∑

(i+1

)∗l+

lcp−

1j=(

i+1)

∗l+l

cp−1

−(lc

s+lc

p−l)

cntj

#include

#include

#include

#define maxn 300000

#define maxlog 19

#define maxc 256

using

namespace

std;

template

void read(t &x)

}}int t,n,array[4][maxn*2+10],*sa,*nsa,*rk,*nrk,b[maxn*2+10],hn,m,st[maxn*2+10][maxlog+1],height[maxn*2+10],log,cnt[maxn+10],lg2[maxn*2+10];

char s[maxn+10];

long

long ans;

void get_sa()

for(k=1;rk[sa[n-1]]1;k<<=1)

swap(rk,nrk);

swap(sa,nsa);

}}void get_height()

}}void read()

void prepare_st()

int get_st(int i,int j)

void solve()}}

for(i=1;i1];

cnt[hn]=0;

for(i=1;i<=hn;i++)

cnt[i]+=cnt[i-1];

for(i=1;i<=hn;i++)

}}void prepare()

int main()

}

NOI2016優秀的拆分 字尾陣列

題目描述 如果乙個字串可以被拆分為 aabb 的形式,其中 a和 b是任意非空字串,則我們稱該字串的這種拆分是優秀的。例如,對於字串 aabaabaa,如果令 a aab,b a,我們就找到了這個字串拆分成 aabb的一種方式。乙個字串可能沒有優秀的拆分,也可能存在不止一種優秀的拆分。比如我們令 a...

NOI2016 優秀的拆分 字尾陣列

題目鏈結 洛谷點我 uoj點我 題目描述 如果乙個字串可以被拆分為 aabb 的形式,其中 a和 b是任意非空字串,則我們稱該字串的這種拆分是優秀的。例如,對於字串 aabaabaa,如果令 a aab,b a,我們就找到了這個字串拆分成 aabb的一種方式。乙個字串可能沒有優秀的拆分,也可能存在不...

NOI2016 優秀的拆分(字尾陣列)

如果乙個字串可以被拆分為aabbaabb的形式,其中 a和 b是任意非空字串,則我們稱該字串的這種拆分是優秀的。例如,對於字串aabaabaa,如果令 a aab,b a,我們就找到了這個字串拆分成 aabb的一種方式。乙個字串可能沒有優秀的拆分,也可能存在不止一種優秀的拆分。比如我們令 a a,b...