C 解題報告 Rima(字典樹 樹形DP)

2021-09-25 08:06:29 字數 2473 閱讀 8278

adrian對單詞押韻很感興趣。如果兩個單詞的最長公共字尾的長度與兩個單詞中較長那個的長度一樣,或者等於較長單詞的長度減一,則這兩個單詞押韻。換句話說,如果a,b的最長公共字尾lcs(a,b)≥max(|a|,|b|)-1,則a和b押韻。

有一天,在閱讀一套短篇**時,他決定創造出能夠使每兩個相鄰單詞押韻的最長的單詞序列,序列中的每個單詞只能出現一次。但是adrian已經厭倦了這個任務,所以他決定回去讀**,並要求你代替他解決這個任務。

第一行輸入包含整數n(1≤n≤5*1e5)。表示單詞的個數。

接下來n行每行包含乙個只由小寫英文本母組成的字串。表示可以用於組成序列的單詞。資料保證每個單詞都是不同的,保證所有單詞的長度之和不超過3*1e6。

輸出乙個整數。表示單詞序列的最長長度。

4

honi

toni

oniovi

3
5

askpsk

krafna

skk

4
5

paskompas

stas

snemarime

1
首先可以知道要用字典樹,將輸入的字串反向插入字典樹(這裡有個坑「保證所有單詞的長度之和不超過3*1e6」,無數次re的血的教訓啊!!!)

for( int i = 1 ; i <= n ; ++ i )
然後看一下資料,有點大,卡空間啊,字典樹不能直接暴力開26來存子節點,用vector來存

vector型別為pair,乙個為字元,另乙個為子節點編號

struct node trie[maxn];
然後就解決了卡空間的問題

求最長序列,不難看出這要樹形dp(毒瘤啊)

「換句話說,如果a,b的最長公共字尾lcs(a,b)≥max(|a|,|b|)-1,則a和b押韻。」,可以看出這個序列只能連續包含節點的兒子或兄弟(相差距離為0或1及深度相差為1或0)

然後處理樹dp

如在x節點(有深色標記的為終節點),不難發現子串行最長為s1的,次長為s2 , x的最長就是s1+s2+s3,而如果又有乙個次次小序列,能否把他也加入x的最長序列呢,顯然是不能的,因為要每兩個相鄰,所以如果加上次次小序列會發現有串會不滿足條件,即以x為中轉點只能連線兩個兒子(很難想,要自己去推,不好口述)

要經過自己的一番思考,可以得出x的最長序列為其最長子序列加次長子序列再加上兒子為終結點的個數

max_ans = max1 + max2 + trie[x].end + max(0,sum_son-2) ;//計算當前的最最長的序列 

ans = max( ans , max_ans );//更新答案

//max1為最大子串行,max2為次大子串行

//trie[x].end表示為該節點是否為終節點,sum_son為子節點為終節點的個數

//max1,max2已經包含了sum_son的兩個節點,要減去

然後就可以快樂的dp了

**詳解,消化理解。。。

#include #include #include #include #include #include #include #define maxn 3000005

using namespace std;

int n , ans , cnt , p ;

struct node trie[maxn];

void iinsert( string a )

} if( get == -5 )

p = get ;

} trie[p].end = 1 ;//標記終節點

}void dfs( int x )

if( trie[x].end )

trie[x].sum += max(1,sum_son);//加上自己或滿足條件的子節點加自己(在trie[x].sum包含乙個子節點)

else trie[x].sum = 0 ;

max_ans = max1 + max2 + trie[x].end + max(0,sum_son-2) ;//計算當前的最最長的序列

ans = max( ans , max_ans );//更新答案

}int main()

dfs(0);

printf("%d", ans );

return 0;

}

HDOJ2846解題報告 字典樹

題目概述 給你p個單詞以及q個詢問,對於每個詢問,回答乙個整數,表示詢問的字串是多少個所給的單詞的子串。大致思路 很容易看出是乙個字典樹的題,因為只要是子串都滿足題意,所以在插入的時候需要多插入一些,例如 對於單詞abcd,則需要插入字串abcd,bcd,cd,d 然後插入的時候順便統計一下個數,這...

HDOJ2072解題報告 字典樹

題目概述 給你一些句子,統計每個句子中單詞的個數。大致思路 這個題有幾種思路,一種是用tire樹,在插入單詞過程中如果新建了乙個節點便說明這個單詞是新單詞,需要注意的是有些單詞可能是另一些的字首,這裡需要特殊處理一下。還有就是stl了,map,set都行,因為我沒有用stl就不細說了。1 inclu...

校門外的樹 解題報告

校門外的樹 某校大門外長度為l的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1公尺。我們可以把馬路看成乙個數軸,馬路的一端在數軸0的位置,另一端在l的位置 數軸上的每個整數點,即0,1,2,l,都種有一棵樹。由於馬路上有一些區域要用來建地鐵。這些區域用它們在數軸上的起始點和終止點表示。已知任一區域的...