upc 6360 詞韻(字典樹上dp)

2021-08-21 18:48:25 字數 1932 閱讀 6666

時間限制: 2 sec  記憶體限制: 128 mb

提交: 134  解決: 18

[提交] [狀態] [討論版] [命題人:admin]

題目描述

adrian 很喜歡詩歌中的韻。他認為,兩個單詞押韻當且僅當它們的最長公共 字尾的長度至少是其中較長單詞的長度減一。也就是說,單詞 a 與單詞 b 押韻 當且僅當 lcs(a, b) ≥ max(|a|, |b|) – 1。(其中 lcs 是最長公共字尾 longest common suffix 的縮寫)

現在,adrian 得到了 n 個單詞。他想從中選出盡可能多的單詞,要求它們能 組成乙個單詞序列,使得單詞序列中任何兩個相鄰單詞是押韻的。

輸入第一行是乙個整數n。

接下來n行,每行乙個由小寫英文本母組成的字串,表示每個單詞。所有單詞互不相同。

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

樣例輸入

5

askpsk

kkrafna

sk

樣例輸出

4
提示

一種最長單詞序列是 ask-psk-sk-k。

30%的測試資料:1 ≤ n ≤ 20,所有單詞長度之和不超過 3 000。

100%的測試資料:1 ≤ n ≤ 500 000,所有單詞長度之和不超過 3 000 000。

2018北京冬令營1

【分析】

將所有單詞逆序,並建立字典樹,單詞結尾結點加標記。

問題就轉化為:

在字典樹上找一條最長的路徑,滿足 ①只走標記結點 ②從結點u可以走向父結點、孩子結點、兄弟結點。

設陣列 fdp[i] 表示以 i 結點為根節點時,可以從任一子樹走上來,剛走到 i 時的最長路徑(這是一條起始於子樹,終結於點 i 的路徑)。如圖藍色結點的藍色路徑為fdp表示最長路徑:

設陣列 dp[i] 表示以i結點為根節點時,把兩個擁有最長fdp的子樹連線起來,順便把所有孩子結點連上的最長路徑(這是一條從子樹起始,終結於子樹的路徑)。如圖粉紅色結點,把兩個擁有最大fdp的孩子連線到自己。

在dfs回溯過程中更新這兩個陣列即可。最後取陣列中的最大值即為答案

【**】

#includeusing namespace std;

typedef long long ll;

const int mod=1e9+7;

const int max=1e6+5;

struct nodeedge[max];

int cnt,head[max],val[max]; //val[i]結點i結尾的單詞數

void init()

void addedge(int u,char ch)

; head[u]=cnt;

}int new_word(char *str)

else if(mxchild>mx[0])mx[0]=mxchild;

mark+=val[i];

}mark+=val[u];

if(mx[0]>0)dp[u]=mx[0]+mx[1]+mark; //連線兩孩子

if(val[u])fdp[u]=mark+mx[1]; //最長單鏈

}char str[max];

int main()

dfs(0);

int ans=0;

for(int i=0;i<=cnt;i++)ans=max(ans,max(dp[i],fdp[i]));

printf("%d\n",ans);

}

636 函式的獨佔時間

題目 給出乙個非搶占單執行緒cpu的 n 個函式執行日誌,找到函式的獨佔時間。每個函式都有乙個唯一的 id,從 0 到 n 1,函式可能會遞迴呼叫或者被其他函式呼叫。日誌是具有以下格式的字串 function id start or end timestamp。例如 0 start 0 表示函式 0...

LeetCode636 函式的獨佔時間

給出乙個非搶占單執行緒cpu的n個函式執行日誌,找到函式的獨佔時間。每個函式都有乙個唯一的 id,從0到n 1,函式可能會遞迴呼叫或者被其他函式呼叫。日誌是具有以下格式的字串 function id start or end timestamp。例如 0 start 0 表示函式 0 從 0 時刻開...

nyoj 636 世界末日

時間限制 1000 ms 記憶體限制 65535 kb 難度 1 描述 世界末日馬上就要來臨了,當然,每個人都想買到船票,但是由於船票有限,因此需要回答對乙個問題才能買票。問題是這樣的 給你乙個數n 1 n 10000 之後給n個正整數 10000 問在這n個數中是否存在一些數的和是n的倍數。輸入 ...