思路:字典树
分析:
1 题目要求的是给以个询问字符串s,在n个物品中找到总共有几个满足s是物品名字的字串。
2 子串问题,那么这里我们可以利用求出n件物品名字的所有的字串(这里要扣除重复),然后建立字典树,最后求总共有几个即可。
3 这个第一个是怎么判断一个字符串的子串已经有了,即假设有字符串“abab”,那么子串“ab”将出现两次,但是只能加1次,所以我们在字典树的节点里面增加一个number,表示当前所要添加的子串来自第几个物品,只要当前的id与节点的number不同就可以加1.
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<map> using namespace std; #define MAXN 1000010 #define N 30 int n , q , cnt; struct Trie{ int number;/*用来记录编号*/ int count;/*count记录单词的个数*/ Trie* child[N]; }trie[MAXN]; Trie *root; /*静态分配空间*/ Trie* newTrie(){ trie[cnt].number = 0; trie[cnt].count = 0; for(int i = 0 ; i < N ; i++) trie[cnt].child[i] = NULL; return &trie[cnt++]; } /*字典树的插入*/ void insert(char *str , int n){ Trie *s = root; int len = strlen(str); for(int i = 0 ; i < len ; i++){ int num = str[i]-'a'; if(s->child[num] == NULL) s->child[num] = newTrie(); s = s->child[num]; } if(s->number != n){/*如果当前的number和n不同说明可以加1*/ s->count++; s->number = n;/*把number改为n*/ } } /*字典树的查找*/ int search(char *str){ Trie *s = root; int len = strlen(str); for(int i = 0 ; i < len ; i++){ int num = str[i]-'a'; if(s->child[num] == NULL) return 0; s = s->child[num]; } return s->count;/*返回总共有几个*/ } int main(){ root = newTrie(); scanf("%d" , &n); int cnt; char ch[N] , words[N] , query[N]; for(int i = 0 ; i < n ; i++){ scanf("%s" , words); int len = strlen(words); for(int j = 0 ; j < len ; j++){ memset(ch , '\0' , sizeof(ch)); cnt = 0; for(int k = j ; k < len ; k++){ ch[cnt++] = words[k]; insert(ch , i+1); } } } scanf("%d" , &q); for(int i = 0 ; i < q ; i++){ scanf("%s" , query); printf("%d\n" , search(query)); } return 0; }
时间: 2024-10-30 16:21:15