FZU 2005 Computer Virus on Planet Pandora (AC自动机)

典型的AC自动机,起初我通过动态开辟空间的方式来申请内存,提交之后果断TLE,后面看到队员佳佳的AC代码发现他是先直接开一个足够大(数组的大小要大于Trie树节点的个数)数组,在申请空间时就分配一个数组元素。后面我也改成了分配数组的方案,果断A了。也正是通过这题让我发现动态申请过大的空间有可能超时。

AC代码如下:

/* Author: ACb0y Date: 2011年1月2日 12:07:42 Type: AC自动机 Result: 366601 2011-01-02 12:05:04 Accepted 2005 GNU C++ 421 ms 42596KB 2685B only_for_today ProblemID: FZU 2005 Computer Virus on Planet Pandora */ #include <iostream> #include <queue> using namespace std; struct node { node * fail; node * next[26]; int word; }; node data[250000]; node * root; char str[5100100]; char x[5100100]; char p[5100100]; int pos; node * get_node() { data[pos].fail = NULL; data[pos].word = 0; memset(data[pos].next, NULL, sizeof(data[pos].next)); return &data[pos++]; } void insert(char * str) { node * p_cur = root; int len = strlen(str); for (int i = 0; i < len; ++i) { int pos = str[i] - 'A'; if (p_cur->next[pos] == NULL) { p_cur->next[pos] = get_node(); } p_cur = p_cur->next[pos]; } p_cur->word++; } void build_fail() { queue<node *> q; root->fail = NULL; q.push(root); while (!q.empty()) { node * p_cur = q.front(); q.pop(); for (int i = 0; i < 26; ++i) { if (p_cur->next[i] != NULL) { if (p_cur == root) { p_cur->next[i]->fail = root; } else { node * temp = p_cur->fail; while (temp != NULL) { if (temp->next[i] != NULL) { p_cur->next[i]->fail = temp->next[i]; break; } temp = temp->fail; } if (temp == NULL) { p_cur->next[i]->fail = root; } } q.push(p_cur->next[i]); } } } } int query(char * str) { int cnt = 0; node * p_cur = root; int len = strlen(str); for (int i = 0; i < len; ++i) { int pos = str[i] - 'A'; while (p_cur->next[pos] == NULL && p_cur != root) { p_cur = p_cur->fail; } p_cur = p_cur->next[pos]; if (p_cur == NULL) { p_cur = root; } node * temp = p_cur; while (temp != root && temp->word != -1) { cnt += temp->word; temp->word = -1; temp = temp->fail; } } return cnt; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int cas; int len; int c; scanf("%d", &cas); while (cas--) { int n; pos = 0; root = get_node(); scanf("%d", &n); while (n--) { scanf("%s", str); insert(str); } build_fail(); scanf("%s", str); len = strlen(str); c = 0; for (int i = 0; i < len; ++i) { if (str[i] != '[') { p[c++] = str[i]; } else { ++i; long q = 0; while (str[i] >= '0' && str[i] <= '9') { q *= 10; q += str[i] - '0'; ++i; } long k = 0; while (str[i] != ']') { x[k++] = str[i]; ++i; } for (long j = 0; j < q; ++j) { for (long jj = 0; jj < k; ++jj) { p[c++] = x[jj]; } } } } p[c] = 0; int ans = 0; ans += query(p); reverse(p, p + strlen(p)); ans += query(p); cout << ans << endl; } return 0; }

你可能感兴趣的:(c,null,query,insert,Build)