Cây tiền tố (Trie) và ứng dụng của cây tiền tố trong các bài toán

27 2.3K 11
Cây tiền tố (Trie) và ứng dụng của cây tiền tố trong các bài toán

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Cây tiền tố (trie)được sử dụng để quản lý và phục vụ tìm kiếm nhanh các đối tượng có phần đầu giống nhau.Ví dụ, khi tìm kiếm trên google.com, nếu ta gõ vào cửa sổ tìm kiếm ký tự “O” hệ thống sẽ đưa ra ra một số đối tượng bắt đầu bằng chữ cái O: “Ola”, “Ongame”, “One piece”, “Oggy”, … Nếu ta gõ tiếp “Ol” thì thông tin đưa ra sẽ là: “Olympus”, “Ola”, “Ola me”, “Ole”, … Khi gõ “Oly” sẽ có nội dung gợi ý lựa chọn: “Olympus”, “Olympic”, “Olympia”, “Olympus has fallen”, … Nếu nội dung gõ trong thanh tìm kiếm là “Olympiad in” thì ở cửa sổ dự báo sẽ có nội dung: “Olympiad india”, “Olympiad in informatics”, “Olympiad inequalities”, “Olympiad in chippenham”, …Cây tiền tố gồm một gốc không chứa thông tin, trên mỗi cạnh lưu một ký tự, mỗi nút và đường đi từ gốc đến nút đó thể hiện một xâu, gồm các ký tự là các ký tự thuộc cạnh trên đường đi đó.Việc tạo và xử lý cây tiền tố là nội dung chủ yếu của các hệ quản trị cơ sở dữ liệu văn bản.Dưới đây ta sẽ xét một số phép xử lý đặc thù trên cây tiền tố thông qua một số bài toán cụ thể.

Cây tiền tố I MỞĐẦU Cây tiền tố (trie)được sử dụng để quản lý phục vụ tìm kiếm nhanh đối tượng có phần đầu giống nhau.Ví dụ, tìm kiếm google.com, ta gõ vào cửa sổ tìm kiếm ký tự “O” hệ thống đưa ra số đối tượng bắt đầu chữ O: “Ola”, “Ongame”, “One piece”, “Oggy”, … Nếu ta gõ tiếp “Ol” thông tin đưa là: “Olympus”, “Ola”, “Ola me”, “Ole”, … Khi gõ “Oly” có nội dung gợi ý lựa chọn: “Olympus”, “Olympic”, “Olympia”, “Olympus has fallen”, … Nếu nội dung gõ tìm kiếm “Olympiad in” cửa sổ dự báo có nội dung: “Olympiad india”, “Olympiad in informatics”, “Olympiad inequalities”, “Olympiad in chippenham”, … Cây tiền tố gồm gốc không chứa thông tin, cạnh lưu ký tự, nút đường từ gốc đến nút thể xâu, gồm ký tự ký tự thuộc cạnh đường Việc tạo xử lý tiền tố nội dung chủ yếu hệ quản trị sở liệu văn bản.Dưới ta xét số phép xử lý đặc thù tiền tố thông qua số toán cụ thể II ỨNG DỤNG CỦA CÂY TIỀN TỐ TRONG CÁC BÀI TOÁN Bài toán 1:Tìm kiếm nhiều mẫu 1.1 Đề (Nguồn: Truyền thống) Cho xâu t tập xâu mẫu s1, s2, …, sn Hãy đếm số lần xuất xâu mẫu xâu t Dữ liệu: Dòng chứa xâu t có độ dài không vượt 5×105 Dòng thứ hai ghi số nguyên n (1 ≤ n ≤ 100) Dòng thứ i n dòng chứa xâu si có độ dài không vượt 15 Các xâu si chứa chữ Latin thường ‘a’ ‘z’ hoa ‘A’ ‘Z’, chữ số ‘0’ ’9’ ký hiệu “!?.,:;-_’#$%&/=*+(){}[]” Xâu t chứa ký tự thêm ký tự dấu cách Chú ý có số xâu mẫu giống vị trí xuất xâu t ta đếm lần Kết quả: Ghi số lần xuất xâu mẫu s1, s2, …, sn xâu t Ví dụ: find_patterns.inp shers he she his he hers find_patterns.out Các xâu mẫu xuất lần xâu t là: shers, shers, shers 1.2 Thuật toán Chúng ta biết số thuật toán tìm kiếm mẫu xâu thuật toán RabinKarp (RK), thuật toán Knuth-Moris-Pratt (KMP) Trong này, xét thuật toán tìm kiếm nhiều mẫu xâu Rõ ràng phương pháp đơn giản để giải toán trênlà ta áp dụng thuật toán Rabin-Karp thuật toán Knuth-Moris-Pratt với xâu mẫu.Thuật toán theo cách có độ phức tạp O(n×m), đón số xâu mẫu vàm độ dài xâu t Một thuật toán hiệu để giải toán tìm kiếm nhiều mẫu phát minh Alfred V Aho Margaret J Corasick gọi thuật toán tìm kiếmnhiều mẫu Aho-Corasick, mô tả sau Đầu tiên tạo trie biểu diễn tập xâu mẫu: • Mỗi cạnh trie có nhãn ký tự • Hai cạnh từ nút có nhãn khác • Nhãn nút v ghép nhãn cạnh đường từ nút gốc tới nút v kí hiệu L(v) Khi với xâu mẫu si, tồn nút v với L(v) = si • Nhãn L(v) nút v xâu mẫu si Ví dụ trie với xâu mẫu “he”, “she”, “his”, “hers” sau: h e “he” r i s s h e s “hers” “his” “she” Đoạn chương trình cài đặt việc tạo trie Giả thiết cho thấy tổng độ dài xâu mẫu không lớn 15×100=1500 nên ta có khai báo biến cài đặt sau int n, to[1501][128], link[1501], word[1501], sz = 0; bool leaf[1501]; void init_trie() { memset(to, 0, sizeof(to)); memset(leaf, false, sizeof(leaf)); memset(link, 0, sizeof(link)); memset(word, 0, sizeof(word)); } void add_str(string s, int id) { int u = 0; for (int i = 0; i < s.size(); i++) { int j = s[i]; if (to[u][s[i]] == 0) to[u][j] = ++sz; u = to[u][j]; } leaf[u] = true; // nut u la diem cuoi cua mot mau word[u] = id; // ghi nhan chi so cua mau } Bây giả sử ta cần tìm kiếm mẫu xâu “shers” Ta nút theo cạnh ‘s’ tới nút 3, từ nút theo cạnh ‘h’ tới nút 4, từ nút theo cạnh ‘e’ tới nút Vì nút nút nên ta ghi nhận có vị trí xuất mẫu (chú ý vị trí cuối mẫu xuất hiện) Nhưng từ nút lại cạnh ‘r’ ra, ta cần phải quay lui lại phía trước xem có mẫu khác xuất không Việc quay lui lại từ đầu mà quay lui lại nút có nhãn phần hậu tố dài nút 5, tức nút Nhưng nút lại nút nên ta lại ghi nhận thêm vị trí mẫu xuất Sau từ nút ta lại theo cạnh ‘r’ tới nút 8, từ nút theo cạnh ‘s’ tới nút Nút nút nên ta lại ghi nhận thêm vị trí mẫu xuất hiện.Đến ta dừng việc tìm kiếm xét đến cuối xâu Như với nút u ta cần biết nút v cho nhãn nút v phần hậu tố dài nhãn nút u ta đặt link[u] = v Các đường nét đứt trie link nút h e “he” r i s s h e s “hers” “his” “she” Thủ tục push_link xác định link cho nút trie: void push_link() { queue q; q.push(0); while (!q.empty()) { int u = q.front(); q.pop(); int v = link[u]; leaf[u] |= leaf[v]; for (int i = 0; i < 128; i++) if (to[u][i] != 0) { link[to[u][i]] = ((u != 0) ? to[v][i] : 0); q.push(to[u][i]); } else to[u][i] = to[v][i]; } } Hàm search_str sau thể việc tìm kiếm mẫu trả lại số mẫu xuất xâu int search_str(string s) { int cnt = 0, u = 0; for (int i = 0; i < s.size(); i++) { u = to[u][s[i]]; int v = u; while (leaf[v]) { if (word[v] != 0) cnt++; v = link[v]; } } return cnt; } Thuật toán Aho-Corasick có độ phức tạp thời gian O(z+n+m), z tổng độ dài xâu mẫu,n số mẫu vàm độ dài xâu 1.3 Chương trình #include using namespace std; int n, to[1501][128], link[1501], word[1501], sz = 0; bool leaf[1501]; string t; void init_trie() { memset(to, 0, sizeof(to)); memset(leaf, false, sizeof(leaf)); memset(link, 0, sizeof(link)); memset(word, 0, sizeof(word)); } void add_str(string s, int id) { int u = 0; for (int i = 0; i < s.size(); i++) { int j = s[i]; if (to[u][s[i]] == 0) to[u][j] = ++sz; u = to[u][j]; } leaf[u] = true; word[u] = id; } void push_link() { queue q; q.push(0); while (!q.empty()) { int u = q.front(); q.pop(); int v = link[u]; leaf[u] |= leaf[v]; for (int i = 0; i < 128; i++) if (to[u][i] != 0) { link[to[u][i]] = ((u != 0) ? to[v][i] : 0); q.push(to[u][i]); } else to[u][i] = to[v][i]; } } int search_str(string s) { int cnt = 0, u = 0; for (int i = 0; i < s.size(); i++) { u = to[u][s[i]]; int v = u; while (leaf[v]) { if (word[v] != 0) cnt++; v = link[v]; } } return cnt; } int main () { freopen("find_patterns.inp", "r", stdin); freopen("find_patterns.out", "w", stdout); init_trie(); getline(cin, t); scanf("%d\n", &n); for (int i = 1; i > i) & 1; if (to[u][1-b] != 0) { num += i) & 1; cnt[u][j]++; // so nut la neu di theo duong di if (to[u][j] == 0) to[u][j] = ++sz; u = to[u][j]; } } int get(int a) { int num = 0; for (int i = 30, u = 0; i >= 0; i ) { int b = (a >> i) & 1; // bit thu i cua a if (((k>>i)&1) == 1) { // bit thu i cua k num += cnt[u][b]; if (to[u][1-b] == 0) break; u = to[u][1-b]; 19 } else { if (to[u][b] == 0) break; u = to[u][b]; } } return num; } int main() { scanf("%d%d", &n, &k); init_trie(); add_bit(0); int pre = 0; for (int i = 1; i = 0; i ) { int j = (a >> i) & 1; cnt[u][j]++; if (to[u][j] == 0) to[u][j] = ++sz; u = to[u][j]; } } int get(int a) { int num = 0, i, u; for (i = 30, u = 0; i >= 0; i ) { int b = (a >> i) & 1; // bit thu i cua a if (((x>>i)&1) == 0) { // bit thu i cua x num += cnt[u][1-b]; if (to[u][b] == 0) break; u = to[u][b]; } else { if (to[u][1-b] == 0) break; u = to[u][1-b]; } } return (i < 0) ? num+1 : num; } int main() { freopen("seg_num.inp", "r", stdin); freopen("seg_num.out", "w", stdout); scanf("%d%d", &n, &x); init_trie(); 21 } add_bit(0); int pre = 0; for (int i = 1; i = 0; i ) { int j = (a >> i) & 1; cnt[u][j]++; if (to[u][j] == 0) to[u][j] = ++sz; u = to[u][j]; } } int get(int a) { int num = 0; for (int i = 30, u = 0; i >= 0; i ) { int b = (a >> i) & 1; // bit thu i cua a if (((x>>i)&1) == 0) { // bit thu i cua x num += cnt[u][1-b]; if (to[u][b] == 0) return num; u = to[u][b]; } else { if (to[u][1-b] == 0) return num; u = to[u][1-b]; } } 23 } return num+1; int main() { freopen("seq_xor.inp", "r", stdin); freopen("seq_xor.out", "w", stdout); scanf("%d%d", &n, &x); init_trie(); add_bit(0); int pre = 0; for (int i = 1; i [...]... ỨNG DỤNG CỦA CÂY TIỀN TỐ TRONG CÁC BÀI TOÁN…………………… 1 Bài toán 1: Tìm kiếm nhiều mẫu……………………………………………………… 1.1 Đề bài 1.2 Thuật toán 1.3 Chương trình 1.4 Test 1.5 Cảm nhận 2 Bài toán 2: Tách từ…………………………………………………………………… 2.1 Đề bài 2.2 Thuật toán 2.3 Chương trình 2.4 Test 2.5 Cảm nhận 3 Bài toán 3: Mật khẩu………………………………………………………………… 3.1 Đề bài 3.2 Thuật toán 3.3 Chương trình 3.4 Test 3.5 Cảm nhận 4 Bài. .. ans); return 0; } 7.4 Test Đường dẫn tải test cho bài toán: https://drive.google.com/file/d/0B-NTUSa9_289SDduMV9Eakk1NFU/view?usp=sharing 7.5 • • • Cảm nhận Bài toán 2 điểm động quy về bài toán 1 điểm động Là sự mở rộng của bài toán 6 qua tính chất của phép xor Ứng dụng của cấu trúc cây tiền tố và tính chất của phép xor 8 Bài toán 8: Xor mảng con 8.1 Đề bài( Nguồn: http://www.spoj.com/problems/SUBXOR/)... printf("%lld\n", ans); return 0; } 8.4 Test Đường dẫn tải test cho bài toán: https://drive.google.com/file/d/0B-NTUSa9_289OVhVMVpCYXlVcGM/view?usp=sharing 8.5 • • • Cảm nhận Là sự mở rộng của bài toán 7 Cũng là bài toán 2 điểm động quy về bài toán 1 điểm động Ứng dụng của cấu trúc cây tiền tố và tính chất của phép xor 9 Bài toán 9: Số lượng khoảng 9.1 Đề bài (Nguồn: Kỹ thuật lập trình - Nguyễn Thanh Tùng - Trường... test cho bài toán: https://drive.google.com/file/d/0B-NTUSa9_289QVdHeGU4TkRqd00/view?usp=sharing 4.5 Cảm nhận Ứng dụng của cây tiền tố trong các bài toán xử lý xâu 5 Bài toán 5: Kiểm duyệt 5.1 Đề bài (Nguồn: USACO 2015) 12 Bác nông dân John đã đặt mua tạp chí Good Hooveskeeping cho các con bò của mình, vì vậy chúng có rất nhiều tài liệu để đọc trong khi chờ đợi để vắt sữa Thật không may trên các tạp... += get(pre); add_bit(pre); } printf("%lld\n", ans); return 0; } 10.4 Test Đường dẫn tải test cho bài toán: https://drive.google.com/file/d/0B-NTUSa9_289ejZvbGZWWVVGbFk/view?usp=sharing 10.5 Cảm nhận Đây là bài toán về ứng dụng của cây tiền tố trong xử lý bít và thứ tự từ điển III KẾT LUẬN Trong các bài toán trên, một thao tác cơ bản cần phải thực hiện là tìm kiếm một dữ liệu:kiểm tra một trạng thái... Test Đường dẫn tải test cho bài toán: https://drive.google.com/file/d/0B-NTUSa9_289aWpBTExYandQa3M/view?usp=sharing 5.5 Cảm nhận Bài toán trên cho ta thấy sự ứng dụng rất đa dạng của cấu trúc dữ liệu cây tiền tố trong xử lý xâu 6 Bài toán 6: Xor lớn nhất 6.1 Đề bài (Nguồn: Sưu tầm) Cho dãy gồm n số nguyên không âm a1, a2, …, an Hãy tìm giá trị xor lớn nhất của 2 phần tử của dãy Ở đây xor là phép tính... printf("%d\n", ans); return 0; } Độ phức tạp thuật toán là: O(n×31) 16 6.4 Test Đường dẫn tải test cho bài toán: https://drive.google.com/file/d/0B-NTUSa9_289TXNzVXF0SkZIUHc/view?usp=sharing 6.5 Cảm nhận Bài toán này cho ta thấy ngoài việc dùng cấu trúc dữ liệu cây tiền tố để xử lý xâu, ta còn ứng dụng vào việc xử lý các dãy bít 7 Bài toán 7: Tổng xor 7.1 Đề bài (Nguồn: Regionals 2009 Asia - Amritapuri)... số, hay trong quá trình quy hoạch động, bạn cần kiểm tra xem một dãy số hay một xâu kí tự có nằm trong một tập cho trước không Để tìm kiếm một cách có hiệu quả là một việc không hề đơn giản Có rất nhiều cấu trúc dữ liệu giúp bạn thực hiện thao tác tìm kiếm: cây tìm kiếm nhị phân, hàm băm, và một cấu trúc dữ liệu rất hiệu quả để xử lý là cây tiền tố (trie) Sau đây là các ưu điểm của cây tiền tố: • Thời... 15 16 17 6.5 Cảm nhận 7 Bài toán 7: Tổng xor…………………………………………………………………… 7.1 Đề bài 7.2 Thuật toán 7.3 Chương trình 7.4 Test 7.5 Cảm nhận 8 Bài toán 8: Xor mảng con…………………………………………………………… 8.1 Đề bài 8.2 Thuật toán 8.3 Chương trình 8.4 Test 8.5 Cảm nhận 9 Bài toán 9: Số lượng khoảng………………………………………………………… 9.1 Đề bài 9.2 Thuật toán 9.3 Chương trình 9.4 Test 9.5 Cảm nhận 10 Bài toán 10: Xor dãy số………………………………………………………………... cho bài toán: https://drive.google.com/file/d/0B-NTUSa9_289Y1E3aEU5REFaX0U/view?usp=sharing 9.5 Cảm nhận Sau khi làm bài toán 8, thì bài toán này là sự ôn tập lại kỹ năng về cấu trúc cây tiền tố 10 .Bài toán 10: Xor dãy số 10.1 Đề bài (Nguồn: VNOI Online 2016) Cho dãy A gồm N số nguyên không âm Ta lần lượt thực hiện Q thao tác trên dãy này: • XORx: Với mọi i: Ai = Aixorx • FINDk: Tìm số lớn thứ k trong

Ngày đăng: 09/09/2016, 22:12

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan