超级传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3430
本题思路清晰,不过解码确实繁琐,看来自己代码能力还有待加强。
需要注意几个点:解码后的ASCII字符的范围是0~255,而且可能包含'\0',不能用char来存,最好用int。
代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #define STATIC_AC_MOTON using namespace std; typedef int Type; const int char_count = 256; const char base_char = 0; typedef struct __node { Type val; int node_data; int vis; struct __node* next[char_count]; struct __node* parent; struct __node* prefix; } Node; #ifdef DYNAMIC_AC_MOTON Node* rt; #endif #ifdef STATIC_AC_MOTON const int max_node_count = 512 * 64 + 10; Node node[max_node_count]; Node* rt = &node[0]; int node_count = 1; #endif int text[8 * 2048 + 10]; char _str[2048 + 10]; void createTree(Node** root) { #ifdef DYNAMIC_AC_MOTON *root = (Node*)malloc(sizeof(Node)); #endif (*root)->val = 0; (*root)->parent = NULL; (*root)->prefix = NULL; (*root)->vis = 0; (*root)->node_data = base_char; for (int i = 0; i < char_count; i++) (*root)->next[i] = NULL; } void deleteTree(Node* root) { #ifdef DYNAMIC_AC_MOTON if (root == NULL) return; for (int i = 0; i < char_count; i++) { if (root->next[i] != NULL) deleteTree(root->next[i]); } free(root); #endif #ifdef STATIC_AC_MOTON node_count = 1; #endif } void insert(Node** root, int* str, int n) { for (int i = 0; i < n; i++) { if ((*root)->next[str[i] - base_char] == NULL) { #ifdef DYNAMIC_AC_MOTON (*root)->next[str[i] - base_char] = (Node*)malloc(sizeof(Node)); #endif #ifdef STATIC_AC_MOTON (*root)->next[str[i] - base_char] = &node[node_count++]; #endif (*root)->next[str[i] - base_char]->parent = *root; root = &((*root)->next[str[i] - base_char]); (*root)->val = 0; (*root)->vis = 0; for (int j = 0; j < char_count; j++) (*root)->next[j] = NULL; } else root = &((*root)->next[str[i] - base_char]); (*root)->node_data = str[i]; if (i == n - 1) (*root)->val++; } } int query(Node* root, int* text, int n) { int count = 0; Node* p = root; int pos = 0; do { while (p != NULL && pos < n) { Node* cnt = p; while (cnt != root && !cnt->vis) { cnt->vis = 1; count += cnt->val; cnt = cnt->prefix; } if (p->next[text[pos] - base_char] != NULL) { p = p->next[text[pos] - base_char]; pos++; } else p = p->prefix; } if (p == NULL) { p = root; pos++; } if (pos == n) { Node* cnt = p; while (cnt != root && !cnt->vis) { cnt->vis = 1; count += cnt->val; cnt = cnt->prefix; } } } while (pos < n); return count; } void make_prefix_pointer(Node* root) { queue<Node*> q; q.push(root); while (!q.empty()) { Node* cnt = q.front(); q.pop(); for (int i = 0; i < char_count; i++) { if (cnt->next[i] != NULL) q.push(cnt->next[i]); } if (cnt == root) { cnt->prefix = NULL; continue; } if (cnt->parent == root) { cnt->prefix = root; continue; } Node* pre = cnt->parent->prefix; while (pre != NULL) { if (pre->next[cnt->node_data - base_char] != NULL) { cnt->prefix = pre->next[cnt->node_data - base_char]; break; } else pre = pre->prefix; } if (pre == NULL) cnt->prefix = root; } } void clearVisFlag(Node* root) { #ifdef DYNAMIC_AC_MOTON if (root == NULL) return; for (int i = 0; i < char_count; i++) clearVisFlag(root->next[i]); root->vis = 0; #endif #ifdef STATIC_AC_MOTON for (int i = 0; i < node_count; i++) node[i].vis = 0; #endif } int decodeBase64ToASCII(int* des, char* src) { int len = strlen(src); int desIndex = 0; int incNum = 0; int zeroBitsCount = 0; int bits[6]; for (int i = 0; i < len; i++) { if (src[i] >= 'A' && src[i] <= 'Z') incNum = src[i] - 'A'; else if (src[i] >= 'a' && src[i] <= 'z') incNum = src[i] - 'a' + 26; else if (src[i] >= '0' && src[i] <= '9') incNum = src[i] - '0' + 52; else if (src[i] == '+') incNum = 62; else if (src[i] == '/') incNum = 63; else if (src[i] == '=') { zeroBitsCount = len - i; break; } for (int j = 0; j < 6; j++) bits[j] = 0; int cntBitIndex = 5; while (incNum) { bits[cntBitIndex--] = incNum % 2; incNum >>= 1; } for (int j = 0; j < 6; j++) des[desIndex + j] = bits[j] + '0'; desIndex += 6; } desIndex -= zeroBitsCount << 1; for (int i = 0; i < desIndex; i += 8) { int val = 0; for (int j = 7; j >= 0; j--) val += (des[i + j] - '0') * (1 << (7 - j)); des[i / 8] = val; } return desIndex / 8; } int main() { int n, m; while (scanf("%d", &n) > 0) { createTree(&rt); for (int i = 0; i < n; i++) { scanf("%s", _str); int len = decodeBase64ToASCII(text, _str); insert(&rt, text, len); } make_prefix_pointer(rt); scanf("%d", &m); for (int i = 0; i < m; i++) { scanf("%s", _str); int len = decodeBase64ToASCII(text, _str); printf("%d\n", n ? query(rt, text, len) : 0); clearVisFlag(rt); } printf("\n"); deleteTree(rt); } return 0; }