还是赤裸裸的DFA,第一次交居然MLE,正苦恼时,看了一眼Discuss,有人说他把数据大小开成80000就过了,我一改,果然过了,汗啊,我之前开的是100000~
/*
* hdu2896/win.cpp
* Created on: 2011-9-22
* Author : ben
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAX_PATTERN_NUM = 510;
const int MAX_PATTERN_LEN = 210;
const int MAXQ = MAX_PATTERN_NUM * MAX_PATTERN_LEN;
const int MAX_TEXT_LEN = 10100;
const int MAXK = 95; //字符集的大小
const char BASE = '!';
typedef struct TrieNode {
TrieNode* fail;
TrieNode* next[MAXK];
bool isaend; //该节点是否为某模式串的终结点
int index; //以该节点为终结点的模式串编号
} TrieNode;
TrieNode *que[MAXQ], *root, CTree[MAXQ];
//文本字符串及模式串
char msg[MAX_TEXT_LEN];
char pattern[MAX_PATTERN_LEN];
int N, nCount;
bool infected[MAX_PATTERN_NUM];
inline TrieNode * NewTrieNode() {
CTree[nCount].index = -1;
return &CTree[nCount++];
}
void TrieInsert(char *s, int index) {
int i = 0;
TrieNode *ptr = root;
while (s[i]) {
int idx = s[i] - BASE;
if (!ptr->next[idx]) {
ptr->next[idx] = NewTrieNode();
}
ptr = ptr->next[idx];
i++;
}
ptr->isaend = true;
ptr->index = index;
}
void Init() {
int i;
root = NewTrieNode();
for (i = 1; i <= N; i++) {
scanf("%s", pattern);
TrieInsert(pattern, i);
}
}
void Build_DFA() {
int rear = 1, front = 0, i;
que[0] = root;
root->fail = NULL;
while (rear != front) {
TrieNode *cur = que[front++];
for (i = 0; i < MAXK; i++) {
if (!cur->next[i]) {
continue;
}
if (cur == root) {
cur->next[i]->fail = root;
} else {
TrieNode *ptr = cur->fail;
while (ptr) {
if (ptr->next[i]) {
cur->next[i]->fail = ptr->next[i];
if (ptr->next[i]->isaend) {
cur->next[i]->isaend = true;
}
break;
}
ptr = ptr->fail;
}
if (!ptr) {
cur->next[i]->fail = root;
}
}
que[rear++] = cur->next[i];
}
}
}
void Run_DFA() {
int i = 0;
TrieNode *ptr = root;
ptr = root;
while (msg[i]) {
int idx = msg[i] - BASE;
while (!ptr->next[idx] && ptr != root) {
ptr = ptr->fail;
}
ptr = ptr->next[idx];
if (!ptr) {
ptr = root;
}
TrieNode *tmp = ptr;
while (tmp && tmp->isaend) {
infected[tmp->index] = true;
tmp = tmp->fail;
}
i++;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int M, total;
while (scanf("%d", &N) == 1) {
nCount = 0;
total = 0;
memset(CTree, 0, sizeof(CTree));
Init();
Build_DFA();
scanf("%d", &M);
for (int i = 1; i <= M; i++) {
memset(infected, false, sizeof(infected));
scanf("%s", msg);
Run_DFA();
int temp = 0;
for (int j = 1; j <= N; j++) {
temp += infected[j];
}
if (temp > 0) {
total++;
printf("web %d:", i);
for (int j = 1; j <= N; j++) {
if (infected[j]) {
printf(" %d", j);
}
}
putchar('\n');
}
}
printf("total: %d\n", total);
}
return 0;
}