hdu 2222 题。。(这题号。。。)http://acm.hdu.edu.cn/showprob…
#include <iostream> #include <stdio.h> #include <memory.h> #include <string> #include <queue> #define CHAR_COUNT 26 class Node { public: Node() { memset(this, 0, sizeof(*this)); } char ch; Node* fail; Node* next[CHAR_COUNT]; int prefix; }; class Trie { public: Node* root; Trie() { root = new Node(); } void insert(const char* str) { Node* p = this->root; for (int i = 0; str[i]; i++) { char ch = str[i]-'a'; if (p->next[ch] == NULL) { p->next[ch] = new Node(); } p = p->next[ch]; p->ch = str[i]; } p->prefix++; } void build() { std::queue<Node*> q; q.push(root); while ( ! q.empty()) { Node* tmp = q.front(); q.pop(); for (int i = 0; i < CHAR_COUNT; i++) { if (tmp->next[i]) { if (tmp == root) { tmp->next[i]->fail = root; } else { Node* p = tmp->fail; while (p) { if (p->next[i]) { tmp->next[i]->fail = p->next[i]; break; } p = p->fail; } if ( ! p) { tmp->next[i]->fail = root; } } q.push(tmp->next[i]); } } } } int query(const char* str) { int ret = 0; Node* p = root; for (int i = 0; str[i]; i++) { char ch = str[i]-'a'; while ( ! p->next[ch] && p != root) { p = p->fail; } p = p->next[ch]; if ( ! p) { p = root; } Node* tmp = p; while (tmp != root && tmp->prefix != -1) { ret += tmp->prefix; tmp->prefix = -1; tmp = tmp->fail; } } return ret; } }; int main() { int t; scanf("%d", &t); while (t--) { Trie trie; int n; scanf("%d", &n); while (n--) { std::string keyword; std::cin>>keyword; trie.insert(keyword.c_str()); } trie.build(); std::string query; std::cin>>query; printf("%d\n", trie.query(query.c_str())); } return 0; }
这个实现是面向对象版本的,说明在这里,http://www.cppblog.com/mythit/…,http://mindlee.net/2011/11/25/…,http://blog.csdn.net/shuangde8…
注意到上面有一个 prefix 这个变量,实际上,是因为题目中,给出的关键词可能有重复的,而对于有重复的关键词,需要计数两次,所以才需要这个东西