BZOJ3790 神奇項鍊

2022-05-20 02:07:41 字數 1394 閱讀 4430

許可權題...

描述:母親節就要到了,小 h 準備送給她乙個特殊的項鍊。這個項鍊可以看作乙個用小寫字

母組成的字串,每個小寫字母表示一種顏色。為了製作這個項鍊,小 h 購買了兩個機器。第乙個機器可以生成所有形式的回文串,第二個機器可以把兩個回文串連線起來,而且第二個機器還有乙個特殊的性質:假如乙個字串的字尾和乙個字串的字首是完全相同的,那麼可以將這個重複部分重疊。例如:aba和aca連線起來,可以生成串abaaca或 abaca。現在給出目標項鍊的樣式,詢問你需要使用第二個機器多少次才能生成這個特殊的項鍊。 

輸入資料有多行,每行乙個字串,表示目標項鍊的樣式。 

多行,每行乙個答案表示最少需要使用第二個機器的次數。 

每個測試資料,輸入不超過 5行 

每行的字串長度小於等於 50000 

題目就是問給定的串最少是由多少個回文串覆蓋構成的

關於回文串首先肯定想的是 manacher

用 manacher 

可以求出每個回文串

題目問的是給定的串最少是由多少個回文串覆蓋構成的

那就變成了經典的線段覆蓋問題

貪心一波就好了:

開乙個陣列 lin[ i ] 表示從第 i 個字元開始的回文串的最長長度

首先第乙個字元一定要被覆蓋到

那麼就選 1~lin[ 1 ] 的線段來覆蓋

然後考慮lin[ 1 ] + 1 的點一定要被覆蓋到

列舉 2~lin[ 1 ] +1 開頭的所有線段,找到右端點最右的線段並選擇

然後考慮更後面的點,用同樣的方法貪心即可

這麼顯然的貪心應該不用證明吧

複雜度 o(n)

然後答案就是選擇的線段數量-1 

**:

#include#include

#include

#include

#include

using

namespace

std;

const

int n=2e5+7

;;char

s[n],a[n];

intf[n],ans;

int lin[n];//

注意此時的lin[i]是在原串時下標i

void

manacher()

}void

slove()

int i=1

;

while(i<=len)

printf(

"%d\n

",ans-1);//

線段數量-1

}int

main()

return0;

}

當然因為資料不大,所以 manacher 可以換成雜湊

列舉中心然後二分可能長度,複雜度o(nlogn)

**就不貼了

bzoj3790 神奇項鍊

傳送門 記一下貪心的方法 從左往右掃。每個回文左端點記錄了回文右端點的位置。l as tlast last 記錄上次的最右端。max rmaxr maxr 記錄從i ii往右走到las tlast last 過程中的最右端。初始化las t ma xr t 0 last maxr t 0 last ...

BZOJ3790 神奇項鍊

想要成為我的master嘛?題目大意 用最少的回文串覆蓋整個字串,可重疊。題解 manacher 貪心 md最近好幾個線段覆蓋的題都沒看出來。manacher算出以每個字元為中心的回文串,就是乙個線段,計算出左端點i len i 1和 右端點i len i 1,然後貪心用每個線段覆蓋區間就好了,兩個...

BZOJ 3790 神奇項鍊

演算法 manacher 貪心 manacher dp 樹狀陣列 線段樹 題解 manacher求回文串,後得到線段,做一點計算對映回原串線段。然後問題轉化為可重疊區間線段覆蓋問題,可以貪心解決。排序左端點,同一左端點取最長段,然後在此段中找到右端點最靠右的線段,線性更新並累加。dp的話 f i 表...