题意:给出n个字符串(数字代表),在给出m个单词,每个单词都有其对应的数字,问对于n中的每一个字符串,求出其在m字符串中出现的次数
第一种方法:比较简单的字典树,对m个字符串建树,然后查询
第二种方法:因为字符串长度不超过6,所以直接使用hash
字典树代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#define lson l,mid,num<<1
#define rson mid+1,r,num<<1|1
using namespace std;
const int M=5005;
struct node
{
int cnt;
node *next[26];
}*p;
char a[M][10];
int ans;
int ss[26]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
void build(char str[],int k, node *head)
{
while(k<strlen(str))
{
if(head->next[str[k]-'a']!=NULL)
{
head->next[str[k]-'a']->cnt++;
head=head->next[str[k]-'a'];
}
else
{
head->next[str[k]-'a']=new node;
head=head->next[str[k]-'a'];
head->cnt=1;
for(int i=0;i<26;i++)
head->next[i]=NULL;
}
k++;
}
}
void search(char str[],int k,node *head)
{
if(head==NULL)return;
if(k==strlen(str))
{
ans+=head->cnt;
return;
}
for(int i=0;i<26;i++)
{
if(ss[i]-(str[k]-'0')==0)
{
search(str,k+1,head->next[i]);
}
}
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
p=new node;
for(int i=0;i<26;i++)
p->next[i]=NULL;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%s",a[i]);
for(int i=0;i<m;i++)
{
char a[10];
scanf("%s",a);
build(a,0,p);
}
for(int i=0;i<n;i++)
{
ans=0;
search(a[i],0,p);
printf("%d\n",ans);
}
}
return 0;
}
Hash 代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#define lson l,mid,num<<1
#define rson mid+1,r,num<<1|1
using namespace std;
const int M=5005;
int a[M];
int hash1[1000100];
int ss[26]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
memset(hash1,0,sizeof(hash1));
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
char s[8];
for(int i=0;i<m;i++)
{
scanf("%s",s);
int sum=0;
for(int j=0;j<strlen(s);j++)
{
sum=sum*10;
sum+=(ss[s[j]-'a']);
}
hash1[sum]++;
}
for(int i=0;i<n;i++)
{
printf("%d\n",hash1[a[i]]);
}
}
return 0;
}