如果乙個字串可以被拆分為 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
4outputaabbbb
cccccc
aabaabaabaa
bbaabaababaaba
354explanation7
我們用 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...