讓我們一起來%forever_shi神犇
題意: 給你n個字串,每次選出若干個字串形成乙個集合,問有多少個集合滿足集合中的任何乙個字串都不是另外乙個字串的字首。空集也一定是滿足條件的。保證不會出現兩個相同的字串。
首先對所有字串建出一棵tri
etrie
trie
樹,然後我們可以發現其實tri
etrie
trie
樹上有用的點只有那些作為某個串的末尾被打上標記的點,於是我們根據tri
etrie
trie
樹上祖先後代的關係對這些有用的點建出一棵新樹來(仍然保留虛根0號點)。
此時我們不難想到,如果新樹上某個點被選了,那麼合法的集合中它的子樹內的所有其他節點都不能被選了;如果某個節點不被選,那麼他每乙個子節點所在的子樹之間的選擇是互不干擾的,就是說不選x
xx時,x
xx的第乙個兒子所在的子樹選出了乙個合法方案,x
xx的第二個兒子所在的子樹選出了乙個合法方案,那麼兩個兒子所在的子樹選的點合起來一定還是合法的。那麼我們設dp[
i]
dp[i]
dp[i
]為以i
ii為根的子樹合法方案的數量,對於同乙個根的不同兒子所在的子樹之間,我們可以用乘法原理來累計方案,最後再加上子樹全部不選只選i自己的方案,就是子樹的方案數。dpdp
dp方程是dp[
x]=1
+∏fa
[y]=
=xdp
[y
]dp[x]=1+\prod_
dp[x]=
1+∏f
a[y]
==x
dp[y
]。最後答案是dp[
0]−1
dp[0]-1
dp[0]−
1,因為不存在只選擇虛根的情況,dp[
0]
dp[0]
dp[0
]中已經包含了選擇空集的情況了。
#include#define ll long long
using namespace std;
struct node
e[100100];
struct nodee
a[100100];
int n,head[100100],num,cnt;
ll dp[10000];
char s[100][100];
void add(int from,int to)
void add1(int x)//建trie樹
a[tmp].cnt=1;//記錄是否是最後乙個字母
}void build(int x,int fa)//建出以末尾為節點的樹
for(int i=1;i<=26;++i)
if(a[x].vis[i])
build(a[x].vis[i],fa);
}void dfs(int x)
dp[x]++;
}int main()
cnt=0;
build(0,0);
dfs(0);
cout
}
字首樹(字典樹,單詞查詢樹,Trie樹)
參考 概述 字首樹又名字典樹,單詞查詢樹,trie樹,是一種多路樹形結構,是雜湊樹的變種,和hash效率有一拼,是一種用於快速檢索的多叉樹結構。典型應用是用於統計和排序大量的字串 但不僅限於字串 所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是 最大限度地減少無謂的字串比較,查詢效率比雜湊表高。t...
Trie樹計算單詞字首的個數
時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 小hi和小ho是一對好朋友,出生在資訊化社會的他們對程式設計產生了莫大的興趣,他們約定好互相幫助,在程式設計的學習道路上一同前進。這一天,他們遇到了一本詞典,於是小hi就向小ho提出了那個經典的問題 小ho,你能不能對於每乙個...
Trie 字首樹 字典樹 單詞查詢樹(資料結構)
在寫完了kmp演算法的部落格之後,我下定決心,一定要寫出一篇關於 ac自動機的部落格 ac自動機實際上就是字典樹上的kmp演算法。所以,考慮到廣大同學不一定會寫trie樹,特此在此處寫了一篇文章介紹介紹這種資料結構。字典樹 又稱單詞查詢樹,trie樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用...