HDU1671——前缀树的一点感触
Posted Coder jily
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU1671——前缀树的一点感触相关的知识,希望对你有一定的参考价值。
题目http://acm.hdu.edu.cn/showproblem.php?pid=1671
题目本身不难,一棵前缀树OK,但是前两次提交都没有成功。
第一次Memory Limit Exceeded:
前缀树是很费空间的数据结构,每个节点存放了字母(数字)个数个指针,正所谓用空间来换取时间。
我发现我忘记写析构函数了,所以测例多起来还不释放很容易超空间。
树形结构的析构也很有趣:
1 ~Node() 2 { 3 for (int i = 0; i < 10; ++i) 4 { 5 if (children[i]) 6 { 7 delete children[i]; 8 children[i] = nullptr; 9 } 10 } 11 }
好了,第二次没成功,Time Limit Exceeded:
看起来这是一棵规规矩矩的前缀树,仔细找可以优化的地方,试探性地把
1 vector<Node *> children; 2 Node() 3 { 4 for (int i = 0; i < 10; ++i) children.push_back(nullptr); 5 }
改成了
1 vector<Node *> children = vector<Node *>(10, nullptr); 2 Node() 3 { 4 //for (int i = 0; i < 10; ++i) children.push_back(nullptr); 5 }
Accepted!显然构造的时候赋值比构造之后再赋值要快。。果然还是要尽可能的优化啊!
附代码:
1 #include <string> 2 #include <vector> 3 #include <iostream> 4 5 using namespace std; 6 7 class Node 8 { 9 public: 10 bool is_phone = false; 11 vector<Node *> children = vector<Node *>(10, nullptr); 12 Node() 13 {} 14 ~Node() 15 { 16 for (int i = 0; i < 10; ++i) 17 { 18 if (children[i]) 19 { 20 delete children[i]; 21 children[i] = nullptr; 22 } 23 } 24 } 25 void insert(const string &_Phone) 26 { 27 Node *p = this; 28 for (int i = 0; i < _Phone.size(); ++i) 29 { 30 int curr = _Phone[i] - ‘0‘; 31 if (p->children[curr] == nullptr) 32 { 33 p->children[curr] = new Node(); 34 } 35 p = p->children[curr]; 36 } 37 p->is_phone = true; 38 } 39 bool has_phone(const string &_Phone) 40 { 41 Node *p = this; 42 for (int i = 0; i < _Phone.size(); ++i) 43 { 44 int curr = _Phone[i] - ‘0‘; 45 if (!p->children[curr]) return false; 46 if (p->children[curr]->is_phone) return true; 47 p = p->children[curr]; 48 } 49 return true; 50 } 51 }; 52 53 typedef Node *Trie; 54 55 int main() 56 { 57 int t; 58 cin >> t; 59 while (t--) 60 { 61 Trie trie = new Node(); 62 int n; 63 cin >> n; 64 string phone; 65 bool flag = true; 66 while (n--) 67 { 68 cin >> phone; 69 if (trie->has_phone(phone)) { flag = false; } 70 trie->insert(phone); 71 } 72 if (flag) cout << "YES" << endl; 73 else cout << "NO" << endl; 74 delete trie; 75 } 76 //system("pause"); 77 return 0; 78 }
以上是关于HDU1671——前缀树的一点感触的主要内容,如果未能解决你的问题,请参考以下文章