1. 程式人生 > 實用技巧 >Trie(字典樹)

Trie(字典樹)

沒時間整理了,老呂又講課了@ @

概念

Trie即字典樹,又稱單詞查詢樹或鍵樹,是一種樹形結構,是一種雜湊樹的變種,典型應用是統計和排序大量的字串(不限於字串)

Trie字典樹主要用於儲存字串,Trie 的每個 Node 儲存一個字元。用連結串列來描述的話,就是一個字串就是一個連結串列。每個 Node 都儲存了它的所有子節點。

基本操作

插入 查詢 字首查詢 刪除

實質:空間換時間

eg:

插入單詞:a,ab,abc,abd,acb

瞅個板子

給定 \(n\) 個長度不超過 \(10\) 的數字串,問其中是否存在兩個數字串 \(S,T\),使得 \(S\)\(T\) 的字首

hash:時間複雜度起飛

這不顯然是字典樹的板子麼

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <string>
#include <cmath>
#include <map>
using namespace std;
const int A = 1e3 + 2;
const int B = 1e4 + 2;
const int C = 1e5 + 5;
const int D = 2e6 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 99984198447;
int read(){
	int x = 0,f = 1;char c = getchar();
	while(c < '0'||c > '9'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0'&&c <= '9'){x = x*10 + c - '0';c = getchar();}
	return x*f;
}
int T, n, tree[C][11],cnt;
bool vis[C],ans;
char s[50];
bool insert(char * s){
	
   int len = strlen(s),u = 1;

   bool flag = false;
   
   for(int i = 0;i < len; i++){

   	   int num = s[i] - '0';
   	   
   	   if(!tree[u][num])
   	   	tree[u][num] = ++cnt;//如果沒有這個字母,就新建一個點 
   	   	
   	   else if(i == len - 1) flag = true;//如果單詞在字典樹中能找到(即字典樹中恰好有這個單詞)
		   
   	   u = tree[u][num];//從新建的點後者原來的點向下走,繼續尋找
		   
   	   if(vis[u])flag = true;//字典中的單詞為新填的單詞的字首 
   }
   vis[u] = true;//將單詞的最後一個字母在字典樹中打上標記 
   return flag;
}
void clear(){//注意清零
    cnt = 1;
	memset(vis, 0,sizeof(vis));
   	memset(tree, 0,sizeof(tree));
    ans = false; 
}
int main(){
   T =  read();
   while(T--){
      n = read();
	  clear();
   	for(int i = 1;i <= n; i++){
   	  	  scanf("%s", s);
   	  	  if(insert(s))ans = true; 
	  }
	 if(!ans)printf("YES\n");
	 else printf("NO\n");
   }
}