hdu 3695 DFA
这题还是比较裸的,可是花了好长时间,一直TLE,最后加上一个优化,当一个字符放到DFA上跑不动的时候,后面相同的字符就直接PASS,终于过了,泪流满面啊……
/*
* hdu3695/win.cpp
* Created on: 2011-9-21
* Author : ben
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAX_PATTERN_NUM = 260;
const int MAX_PATTERN_LEN = 1100;
const int MAXQ = 500000;
const int MAXK = 26; //字符集的大小
const char BASE = 'A';
typedef struct TrieNode {
TrieNode* fail;
TrieNode* next[MAXK];
bool isaend; //该节点是否为某模式串的终结点
int index; //以该节点为终结点的模式串编号
} TrieNode;
TrieNode *myqueue[MAXQ], *root, CTree[MAXQ];
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;
char s[MAX_PATTERN_LEN];
root = NewTrieNode();
for (i = 0; i < N; i++) {
scanf("%s", s);
getchar();
TrieInsert(s, i);
reverse(s, s + strlen(s));
TrieInsert(s, i);
}
}
void Build_DFA() {
int rear = 1, front = 0, i;
myqueue[0] = root;
root->fail = NULL;
while (rear != front) {
TrieNode *cur = myqueue[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;
}
}
myqueue[rear++] = cur->next[i];
}
}
}
void Run_DFA() {
int temp;
char c = getchar();
TrieNode *ptr = root;
TrieNode *last = NULL;
ptr = root;
while (c > ' ') {
temp = 1;
if (c == '[') {
scanf("%d%c]", &temp, &c);
}
while (temp--) {
last = ptr;
int idx = c - 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;
}
if (ptr == last) {
break;
}
}
c = getchar();
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &N);
nCount = 0;
memset(CTree, 0, sizeof(CTree));
Init();
Build_DFA();
memset(infected, false, sizeof(infected));
Run_DFA();
int ans = 0;
for (int i = 0; i < N; i++) {
ans += infected[i];
}
printf("%d\n", ans);
}
return 0;
}