思路:AC自动机模板
分析:
1 题目要求找出相应的字符串在源码串中出现的次数,并且告诉我们字符串只有大写字母。其实解法是一样的,只是别被大写字母这个给限制了,还是相当于建立trie,但是不能单建立大写字母的trie树。
2 当匹配到一个单词的时候就把单词对应的编号对应的个数加加。
代码
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define MAXN 2000010 #define MAX 1010 #define N 100 int n , cnt; int vis[MAX]; char words[MAX][N*2]; char text[MAXN]; struct Node{ Node *next; Node *child[N]; int number; }; Node node[MAXN]; Node *root; queue<Node*>q; Node* newNode(){ node[cnt].next = NULL; node[cnt].number = 0; for(int i = 0 ; i < N ; i++) node[cnt].child[i] = NULL; return &node[cnt++]; } void insert(char *str , int x){ int len = strlen(str); Node *p = root; for(int i = 0 ; i < len ; i++){ int num = str[i]-32;/*不能只建立大写字母的trie树*/ if(p->child[num] == NULL) p->child[num] = newNode(); p = p->child[num]; } p->number = x; } void getNext(){ while(!q.empty()) q.pop(); q.push(root); root->next = NULL; while(!q.empty()){ Node *p = q.front(); q.pop(); for(int i = 0 ; i < N ; i++){ if(p->child[i]){ q.push(p->child[i]); Node *tmp = p->next; while(tmp){ if(tmp->child[i]){ p->child[i]->next = tmp->child[i]; break; } tmp = tmp->next; } if(tmp == NULL) p->child[i]->next = root; } } } } void find(){ int len = strlen(text); Node *p = root; for(int i = 0 ; i < len ; i++){ int num = text[i]-32; while(p->child[num] == NULL && p != root) p = p->next; if(p->child[num]){ p = p->child[num]; Node *tmp = p; while(tmp){ if(tmp->number) vis[tmp->number]++;/*编号加加*/ tmp = tmp->next; } } } } /*输出*/ void output(){ for(int i = 1 ; i <= n ; i++){ if(vis[i]) printf("%s: %d\n" , words[i] , vis[i]); } } int main(){ while(scanf("%d" , &n) != EOF){ cnt = 0; root = newNode(); memset(vis , 0 , sizeof(vis)); for(int i = 1 ; i <= n ; i++){ scanf("%s" , words[i]); insert(words[i] , i); } getchar(); gets(text); getNext(); find(); output(); } return 0; }