hdu 3065 刚A了道题,很艰难,贴下代码。。
病毒侵袭持续中 |
http://acm.hdu.edu.cn/showproblem.php?pid=3065
Accepted |
375MS |
8732K |
3043B |
C++ |
// 今天好不容易把自动机学会了,AC了一道题,不过我自己写的代码还有看不懂的,请大牛指教。。。。
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <queue>
#include <cctype> // 用于 isupper, 判断是否为大写字母
#include <iostream>
#include <string>
using namespace std;
class TrieTree {
private:
static const int MAXELEM = 26;
TrieTree *next[MAXELEM];
TrieTree *fail;
int id;
public:
TrieTree() : id(-1), fail(NULL) {
memset(next, 0, sizeof (next));
}
int &operator[](string s) {
TrieTree *p = this;
for (int h = 0; h < s.length(); ++h) {
assert(isupper(s[h])); // 断言 *s 是一个大写字母 ,如果断言失败,程序终止 退出值 3
int i = s[h] - 'A';
if (p->next[i] == NULL) p->next[i] = new TrieTree;
p = p->next[i];
}
return p->id;
}
void build() {
queue<TrieTree*> q;
this->fail = NULL;
for (int i = 0; i < MAXELEM; ++i) {
if (next[i] == NULL)continue;
next[i]->fail = this;
q.push(next[i]);
}
while (!q.empty()) {
TrieTree * p = q.front();
q.pop();
for (int i = 0; i < MAXELEM; ++i) {
if (p->next[i] == NULL)continue;
q.push(p->next[i]);
TrieTree *tmp = p->fail;
while (tmp && tmp->next[i] == NULL)
tmp = tmp->fail;
if (tmp) p->next[i]->fail = tmp->next[i];
else p->next[i]->fail = this;
}
}
}
void match(string text, int *hash) { //匹配 ,将对应 id 存到hash数组中
TrieTree *p = this;
for (int h = 0; h < text.length(); ++h) {
if (!isupper(text[h])) {
p = this;
continue;
}
int i = text[h] - 'A';
while (p && p->next[i] == NULL)
p = p->fail;
if (p)p = p->next[i];
else p = this;
for (TrieTree *tmp = p; tmp != this; tmp = tmp->fail) {
if (tmp->id != -1)++hash[tmp->id];
}
}
}
~TrieTree() { //回收内存,不回收好像也能过,数据有点弱
for (int i = 0; i < MAXELEM; ++i) {
if (next[i]) delete next[i];
}
}
};
int main(int argc, char** argv) {
int n;
while (cin >> n) {
string *in = new string[n];
TrieTree tree;
for (int i = 0; i < n; ++i) {
cin >> in[i];
tree[in[i]] = i;
}
tree.build();
string text;
cin >> text;
int *hash = new int[n];
memset(hash, 0, sizeof (int) *n);
tree.match(text, hash);
for (int i = 0; i < n; ++i) {
if (hash[i] != 0) cout << in[i] << ": " << hash[i] << endl;
}
delete []in;
delete []hash;
}
return EXIT_SUCCESS;
}