題目傳送門
題目大意:給出乙個字串,求出這個柿子的值:∑1≤
i nlen (ti) +len (tj) −2×l cp(t i,tj )\sum\limits_ 2 2(n−1) ×n×( n+1) 。然後考慮後面如何求出任意兩個字尾的最長公共字首之和,把串反過來,就變成了求任意兩個字首的最長公共字尾。 建出sam,考慮每乙個狀態的貢獻,假設乙個狀態的 end po sendpos endpos 集大小為 siz e[i] size[i] size[i ],就說明其中任意乙個子串都恰好出現過 siz e[i] size[i] size[i ] 次,對於任意乙個子串,假設他在 [a, b] [a,b] [a,b ] 和 [c, d] [c,d] [c,d ] 出現過,那麼以 b bb 結尾和以 d dd 結尾的字首的最長公共字尾至少會延伸到 a,c a,ca, c 這兩個位置,所以可以提供 1 11 的貢獻,至於在 a+1 a+1a+ 1 和 c+1 c+1c+ 1 位置的匹配,自然會有 [a+ 1,b] [a+1,b] [a+1,b ] 和 [c+ 1,d] [c+1,d] [c+1,d ] 兩個子串來提供貢獻 ,一共有 siz e[i] ×(si ze[i ]−1) size[i]\times(size[i]-1) size[i ]×(s ize[ i]−1 ) 種這樣的情況,所以貢獻就是 siz e[i] ×(si ze[i −1]) size[i]\times (size[i-1]) size[i ]×(s ize[ i−1] )。而乙個狀態內有 len (i)− len( link (i)) len(i)-len(link(i)) len(i) −len (lin k(i) ) 個子串,所以貢獻再乘上這個數量即可。 **如下:#include
#include
#include
using
namespace std;
#define maxn 1000010
#define ll long long
int n;
char s[maxn]
;struct statest[maxn]
;int id=
0,last=
0,now,p,q;
int size[maxn]
;void
extend
(int x)
} last=now;
}int c[maxn]
,a[maxn]
;void
get_size()
intmain()
題解 AHOI2013 作業(莫隊)
有一段時間沒寫莫隊,今天wzb分享這道題,ssw02一看,我可以用莫隊水,寫的挺快的 歡迎 ssw02的部落格 給定長為n的序列 m個詢問,每次詢問在 下標在 l r 之間 數值在 a b 之間的數的種類和總數 n,m都是在1e5 的範圍內 可以離線,資料支援根號演算法,所以我們可以考慮分塊 總數和...
AHOI2013 找硬幣(搜尋)
time limit 10 sec memory limit 64 mb submit 348 solved 114 submit status 小蛇是金融部部長。最近她決定製造一系列新的貨幣。假設她要製造的貨幣的面值為x1,x2,x3 那麼x1必須為1,xb必須為xa的正整數倍 b a 例如1,5...
BZOJ3238 AHOI2013 差異 題解
參考 第一道接觸字尾樹的題,然而不想講這個東西。我們只需要知道將串倒著建字尾自動機parent樹就是字尾樹即可。然後兩個字尾的lcp就是他們的lca的len。設點u,則過點u的字尾就有su子樹的size和個,所以能配出size u size u 1 2個對,這條路徑的長度貢獻為 tr u l tr ...