題目大意:給你乙個字串,求所有子串的所有優秀拆分總和,優秀的拆分被定義為乙個字串可以被拆分成4個子串,形如$aabb$,其中$aa$相同,$bb$相同,$ab$也可以相同
作為一道國賽題,95分竟然就這麼給我們了!只是乙個$noip$難度的雜湊套$dp$啊......
95分就是從後往前找,統計$aa$串,每次統計一下從這個位置開始的所有子串 和 緊隨其後的等長串 相同的個數$sum$
$hash(i,i+j-1)==hash(i+j,i+2*j-1) sum[i]++$
然後再統計$bb$串,就是加上在這兩個串之後的位置的$sum$值,這樣就統計出了合法拆分數
$dp[i]+=sum[i+2*j]$
95分就這樣到手啦,竟然連自然溢位hash都不卡
1 #include 2 #include 3 #include 4 #include 5接下來才是本題的重點!$noi$豈是你想$ak$就$ak$的!出題人可能是想針對某位巨佬#define ll long long
6#define ull unsigned long long
7#define n 2050
8#define seed 233
9#define idx(x) (x-'a'+1)
10using
namespace
std;
11//
re12
intt,len;
13char
str[n];
14int
dp[n],sum[n];
15ull hsh[n],sp[n];
16 ull ghsh(int x,int y)
17void
clr()
1824
intmain()
2544}45
}46int ans=0;47
for(int i=1;i<=len;i++)
48 ans+=sum[i];
49 printf("
%d\n
",ans);50}
51return0;
52 }
不看題解這個正解思路真是很難想到......
思路大概是這樣的,其實我們每次只需要統計$aa$串的數量就行了,因為$aabb$串的數量等於,在$i-1$位結束的$aa$串的數量乘以在第$i$位開始的$aa$串的數量,用公式表示就是
接下來就是統計$st$和$ed$了,感覺正解的思路很神
先用字尾陣列+$st$表處理出任意兩個位置,作為字尾串開頭的$lcp$以及作為字首串末尾的$lcs$,求$lcs$可以把串反著讀再去套$sa$
每次選取乙個$a$串的長度$len$,再在原串每隔$len$的位置設乙個關鍵點
然後會發現乙個神奇的性質,任意乙個長度為$2*len$的串必然經過且僅經過2個關鍵點!
接下來統計經過所有長度為$2*len$所有$aa$串,比如選定兩個關鍵點$a,b$,且$a+len=b$
如果把$a$的和b$相同的字首和字尾拼在一起,且拼完之後長度》=len,說明存在至少乙個$aa$串
可以把$aa$串想象成乙個塊,在兩個關鍵點上移動,塊的左端點不能大於$a$,塊的右端點不能小於$b$,塊不能移動到上乙個或者下乙個關鍵點的位置,塊內必須是$aa$串,這樣,塊所有能移動的位置-塊的長度$len$,就是經過$ab$兩個關鍵點的所有$aa$串數
時間變成
,$logn$是調和級數的近似值
細節比較多需要仔細思考
1 #include 2 #include 3 #include 4 #include 5#define ll long long
6#define n 30100
7#define seed 233
8#define idx(x) (x-'a'+1)
9using
namespace
std;
10//
re11
intt,len;
12int
lg[n];
13ll st[n],ed[n],s[n],e[n];
14struct
suffix
21void
get_suffix()
2239
for(i=1;i<=len;i++)
4046}47
void
get_st()
4855
int query(int x,int
y)56
58}p,s;
59void
clr()
6065
intmain()
6698}99
for(int i=1;i<=len;i++)
100 st[i]=st[i-1]+s[i],ed[i]=ed[i-1]+e[i];
101 ll ans=0
;102
for(int i=2;i<=len;i++)
103 ans+=ed[i-1]*st[i];
104 printf("
%lld\n
",ans);
105}
106return0;
107 }
NOI2016優秀的拆分 字尾陣列
題目描述 如果乙個字串可以被拆分為 aabb 的形式,其中 a和 b是任意非空字串,則我們稱該字串的這種拆分是優秀的。例如,對於字串 aabaabaa,如果令 a aab,b a,我們就找到了這個字串拆分成 aabb的一種方式。乙個字串可能沒有優秀的拆分,也可能存在不止一種優秀的拆分。比如我們令 a...
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...