传送门 (<---可以点击的~)
时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte
描述
有些英语单词后缀都是一样的,现在我们需要从给定的一堆单词里面找出某个后缀的单词个数。
输入
输入有多组数据。
每组第一行输入n,m,0<=n,m<=100000,
第二行到n+1行:输入单词,每个单词仅有小写英文字母组成,长度不超过10。
第n+2行到n+m+1行,输入要找的单词后缀。
输出
在n个单词里面找出输入单词后缀的单词个数,然后输出。每个数据与数据之间换行。
样例输入
6 3
someone
everyone
outside
inside
somebody
nobody
one
side
body
样例输出
2
2
2
思路:既然是求后缀个数,把字符串倒一倒就变求前缀个数了,然后就是写字典树。这题的话,map瞎搞也是能过的,耗时在800MS左右(感觉还是老老实实字典树吧~)
拿来练字典树模板的。
字典树代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; typedef long long LL; char str[10100]; struct note{ note* nxt[27]; int sum;//保存出现个数 note(){ sum = 0; memset(nxt,0,sizeof(nxt)); } }a[200010]; void insert(note *root,char s[]){ note *p = root; int i = 0; while(s[i]){ int j = s[i++] - 'a'; if(p->nxt[j] ==NULL){ p->nxt[j] = new note(); } p = p->nxt[j]; (p->sum) ++;//在构建的时候直接把当前结点的sum+1 说明出现过后缀 } } int search(note *root ,char s[]){ note *p = root; int i = 0; while(s[i]){ int j = s[i++]-'a'; if(p->nxt[j] == NULL)return 0; p = p -> nxt[j]; } return p -> sum; } int main(){ int n,m; while(~scanf("%d %d",&n,&m)){ note * root = new note(); while(n--){ scanf("%s",str); strrev(str); insert(root,str); } while(m--){ scanf("%s",str); strrev(str); printf("%d\n",search(root,str)); } } return 0; }
map代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<cstdlib> #include<cmath> #include<stack> #include<vector> #include<map> #include<queue> #include <sstream> #define LL long long using namespace std; map<string,int>ma; int main(){ int n,m; string s; char str[1010]; while(~scanf("%d%d",&n,&m)){ ma.clear(); while(n--){ cin>>s; reverse(s.begin(),s.end()); while(s.size()>0){ ma[s]++; s.erase(s.size()-1); } } while(m--){ scanf("%s",str);strrev(str); printf("%d\n",ma[str]); } } }