Noi2016 優秀的拆分

2022-03-27 10:17:52 字數 2106 閱讀 3939

如果乙個字串可以被拆分為 aabb的形式,其中 aa 和 bb 是任意非空字串,則我們稱該字串的這種拆分是優秀的。例如,對於字串 aabaabaa,如果令 a=aab,b=a,我們就找到了這個字串拆分成 aabb的一種方式。乙個字串可能沒有優秀的拆分,也可能存在不止一種優秀的拆分。比如我們令 a=a,b=baa,也可以用 aabb表示出上述字串;但是,字串 abaabaa 就沒有優秀的拆分。現在給出乙個長度為 n 的字串 s,我們需要求出,在它所有子串的所有拆分方式中,優秀拆分的總個數。這裡的子串是指字串中連續的一段。

以下事項需要注意:

出現在不同位置的相同子串,我們認為是不同的子串,它們的優秀拆分均會被記入答案。在乙個拆分中,允許出現 a=b。例如 cccc 存在拆分 a=b=c。字串本身也是它的乙個子串。

每個輸入檔案包含多組資料。輸入檔案的第一行只有乙個整數 t,表示資料的組數。保證 1≤t≤10。接下來 t 行,每行包含乙個僅由英文小寫字母構成的字串 s,意義如題所述。n≤30000

輸出 t 行,每行包含乙個整數,表示字串 s 所有子串的所有拆分中,總共有多少個是優秀的拆分。

4aabbbb

cccccc

aabaabaabaa

bbaabaababaaba35

47

$sa$的力量= =

顯然我們不用處理什麼$aabb$,只需要去處理所有$aa$形式,再去統計答案即可

設$pre[i]$表示以$i$這個字元開頭的$aa$型子串的數目

設$nxt[i]$表示以$i$這個字元結尾的$aa$型子串的數目

則答案$ans=\sum _^pre[i+1]\times nxt[i]$

所以問題就轉化成了求$aa$型的子串

我們可以列舉找的$aa$型子串長度的一半,去判斷$lcp$與$lcs$

列舉$i=k*len$,$j=i+len$

設$x=lcp(suffix(i),suffix(j))$,$y=lcs(pre(i-1),pre(j-1))$

若$x+y\geqslant len$,那麼我們就找到了$x+y-len+1$個長度為$2\times len$的$aa$串

差分一下就$gg$了

1 #include2 #include3 #include4

using

namespace

std;

5#define mem(x) memset((x),0,sizeof((x)))

6struct

sa12 inline void

clear()

16 inline void

init()

20 inline void

suffix()

39for(i=1;i<=n;++i)rank[sa[i]]=i;

40for(i=1;i<=n;height[rank[i++]]=k)

41for(k?--k:0,j=sa[rank[i]-1];s[i+k]==s[j+k];++k);42}

43 inline void

st()

49 inline int lcp(int x,int

y)59 inline void

work()

63}a,b;

64 inline void

inv()

69 typedef long

long

l;70

l ans;

71 l cnt1[30005],cnt2[30005

];72 inline void

doit()85}

86for(int i=1;i<=a.n;++i)

87 cnt1[i]+=cnt1[i-1],cnt2[i]+=cnt2[i-1

];88

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

89 ans+=cnt1[i+1]*cnt2[i];

90 printf("

%lld\n

",ans);91}

92int

main()

103 }

view code

NOI2016 優秀的拆分

看到題目,資料範圍有點怪異。對於95 的資料,對於100 的資料,意思是只有5分是正解。好吧,95pts的 很明顯,答案就是 而如何才能拿到100pts呢?我們可以先列舉a段的長度,很明顯每個長度為lcp,與往後求lcs,若 這樣就可以通過 include include include inclu...

NOI2016 優秀的拆分

題目實際上要求我們求從每個點出發的aa串的數量 考慮點i的答案,發現如果字首i與字首j j i 的最長公共字尾 i j,那麼i點出發向前就存在乙個長度為i j的aa串,題目即求對於每個字首,有多少個在他之前的字首滿足條件 考慮字尾自動機,由於每個字首都是字尾自動機parent樹上的一點,即兩個字首的...

NOI2016 優秀的拆分

點此看題 首先轉化問題,我們可以求出a i b i a i b i a i b i 即以i ii結束 開始的aaaa aa串的數量,這樣答案就可以表示為 a i b i 1 sum a i times b i 1 a i b i 1 求這兩個陣列,可以隔距離len lenle n設定乙個點,這樣乙個...