NOI2016優秀的拆分 字尾陣列

2021-07-29 23:01:47 字數 1399 閱讀 7398

題目描述

如果乙個字串可以被拆分為 aabb 的形式,其中 a和 b是任意非空字串,則我們稱該字串的這種拆分是優秀的。

例如,對於字串 aabaabaa,如果令 a=aab,b=a,我們就找到了這個字串拆分成 aabb的一種方式。

乙個字串可能沒有優秀的拆分,也可能存在不止一種優秀的拆分。比如我們令 a=a,b=baa,也可以用 aabb表示出上述字串;但是,字串 abaabaa 就沒有優秀的拆分。

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

以下事項需要注意:

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

2.在乙個拆分中,允許出現 a=b。例如 cccc 存在拆分 a=b=c。

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

分析:

1.首先由題目想到列舉斷點,再統計以當前點為結尾的aa串的個數和以下一位為開頭的aa串的個數。

2.具體而言,可以列舉a的串長l,再令i=k*l,j=k*(l+1),分別統計出字尾i和字尾j的最長公共字首r以及字首i-1和j-1的最長公共字尾l,可以發現當(l+r)>=l 時,就會出現相應的一段區間滿足條件,再利用查分的思想統計答案即可。細節較多,需要仔細思考。

#include

#include

#include

#include

using

namespace

std;

const

int maxn=300010;

int n;

int log[maxn];

int pre[maxn],suf[maxn];

struct saffix_array

void build_sa(int m)

if(p>=n) break;

m=p;

}memcpy(rank,x,sizeof(rank));

int k=0;

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

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

for(int i=1;i+(1

<1],height[i+(1

<<(j-1))][j-1]);}}

int lcp(int x,int y)}}

for(int i=1;i<=n;i++) pre[i]+=pre[i-1],suf[i]+=suf[i-1];

long

long ans=0;

for(int i=1;i<=n;i++) ans+=pre[i]*suf[i+1];

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

}return

0;}

NOI2016 優秀的拆分 字尾陣列

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

字尾陣列 NOI2016 優秀的拆分

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

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

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