字典樹(等待更新)

2021-08-21 07:50:33 字數 2098 閱讀 5212

給出乙個由s(最多4000個)個不同單詞組成的字典和乙個長字串。把這個字串按字典分解成若干個單詞的連線,有多少種方法?(方法數可能很多,結果對20071027取模)

比如有4個單詞:a、b、cd、ab,則abcd有兩種分解方法:a+b+cd和ab+cd。(字典中單詞個數不超過4000)

【輸入】

abcd

4 a

b cd

ab 【輸出】

case 1: 2

你會怎麼做呢?去一一比較嗎?這也太傻了誒。

所以就有種叫做字典樹的東西啦!

字典樹(trie),又稱字首樹。是查詢樹的一種。主要用於大量字串的儲存,查詢。搜尋引擎通常利用字典樹完成使用者的搜尋提示。

比如像這樣的圖,tea,ted,ten,to,inn就被我分解成了乙個這樣的樹,也就是說,字典樹在本質上是一棵26叉樹。當你要找乙個單詞是,就是從第乙個字母開始往下找,直到找到葉子,就找到了這個單詞。

那麼具體怎麼實現呢?

先以引題為例子,

1.用d[i]表示以第i個字元到字串末尾的字串能夠分解得單詞數,

2.假設在s[i…length(s)]中,僅發現s[i…n]是字典中出現的單詞,n是該單詞的長度,此時d[i]=d[i+n],(這裡該怎麼理解呢?這樣說,因為該單詞是僅發現的,說明從i到n裡有也只有這麼乙個單詞不能再拆分了,所以d[i]=1*d[i+n])

3.所以,d[i]=sum(d[i+len(x)]),假定x是乙個出現的字首字串(2中的s[i…n])

4.但是,如果列舉x,再判斷它是否為s[i…len]的字首,複雜度是o(4000*len);

那麼,字典樹!

以該圖為例

我們很容易發現字典樹有以下幾個特點:

1.根節點為空,

2.內節點一般為字元

3.葉子結點就是往下搜到的單詞結點

然後呢,用兩個陣列來儲存這棵樹

1.ch[i][j]=x,表示第i號結點的子結點序號是x,儲存的字元的ascii碼是j;

2.val[i],表示第i號結點的附加資訊,比如val[i]>0表示i是單詞結點。(這個val陣列是要你自己在造樹的時候遇到葉子結點再把它手動賦值為大於0)

接下來展示字典樹的插入和查詢

const

int maxnode = 400*100+10;

const

int sigma=26;

struct tire

int idx(char c) ;

void insert(char *s, int v);

void find(char *s);

}void insert(char *s, int v) //v是附加資訊,0表示「非單詞結點」

u = ch[u][c];//接下來的字元則是以u為根節點往下延伸了,就是比如說beautiful,當e作為b的子節點之後,就要去做a是e的子節點了

}val[u]=v;

} void find(const

char *s, int len, vector

& ans)

}} char str[30001], tmp[101];

int d[30001];

trie t;

int main()

printf("case %d: ",case++);

solve();

}return0;}

void solve()

}printf("%d\n",d[0]);

}

字典樹 Trie樹(持續更新)

今天開始學習字典樹,順便做做筆記,等多刷幾道題再來更新一波經驗 字典樹,又稱單詞查詢樹 字首樹 鍵樹,是一種樹形結構,是一種雜湊樹的變種。1 根節點不包含字元,除根節點外每乙個節點都只包含乙個字元。2 從根節點到某一節點,路徑上經過的字元連線起來,為該節點對應的字串。3 每個節點的所有子節點包含的字...

01字典樹(待更新)

01字典樹典型的題就是找出異或值最大的兩個數,其實跟字典樹差不多的,就是從原來的26位字母變成了0和1,插入操作也跟字典樹差不多,查詢的時候有貪心思想,盡量找同位不相同的。模板 1 include2 include3 include4 include5 using namespace std 67 ...

Trie樹(字典樹)

trie樹的核心思想是用空間換時間,通過在樹中儲存字串的公共字首,來達到加速檢索的目的。例如,對於一棵儲存由英文本母組成的字串的trie樹,如下圖 trie樹在實現的時候,可以用左兒子右兄弟的表示方法,也可以在每個節點處開設乙個陣列,如上圖的方法。trie樹的主要操作是插入 查詢,也可以進行刪除。插...