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 这个变量,实际上,是因为题目中,给出的关键词可能有重复的,而对于有重复的关键词,需要计数两次,所以才需要这个东西