http://acm.hdu.edu.cn/showproblem.php?pid=4287
很有意思的一道题
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"algorithm"
using namespace std;
struct Trie
{
struct Trie * next[26];
int flag;
int sum;
};
Trie *H = NULL;
char nn[10][5] = {"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; //预先处理一下,方便使用
char xx[5005][10];
char yy[5005];
int vis[10];
int sum;
Trie * init()
{
Trie * t = new Trie;
for(int i = 0;i < 26;i++)
{
t ->next[i] = NULL;
}
t ->flag = 0;
t ->sum = 0;
return t;
}
void Add(char * s)
{
Trie * t = H;
int len = strlen(s);
vis[len] ++;
for(int i = 0;i < len;i++)
{
int k = s[i] - 'a';
if(t ->next[k] == NULL)
{
t ->next[k] = init();
}
t = t->next[k];
}
t ->flag = 1;
}
void Search(char * s,int len,int step,Trie * l) //用递归来找电话号的排列
{
if(step == len)
{
if(l ->flag)
sum ++; //用全局变量来记录
return ;
}
int k = strlen(nn[s[step] - '0' - 2]); //别忘了存的时候是0为下标,而且是数字二开始,所以要-2
for(int i = 0;i < k;i ++)
{
int kk = nn[s[step]- '0' - 2][i] - 'a';
if(l ->next[kk] != NULL) //当发现没出现过的就跳过
Search(s,len,step + 1,l ->next[kk]);
}
}
void Cls(Trie * l)
{
for(int i = 0;i < 26;i++)
{
if(l ->next[i] != NULL)
{
Cls(l ->next[i]);
}
}
free(l);
}
int main()
{
int a,b,c,d;
while(~scanf("%d",&a))
{
while(a--)
{
H = init();
memset(vis,0,sizeof(vis));
scanf("%d %d",&b,&c);
for(int i = 0;i < b;i++)
{
scanf("%s",xx[i]);
}
for(int i = 0;i < c;i++)
{
scanf("%s",yy);
Add(yy);
}
for(int i = 0;i < b;i++)
{
sum = 0;
int l = strlen(xx[i]);
if(vis[l])
Search(xx[i],l,0,H); // 传过去的分别是 当前字符串数组, 字符串长度 , 字符串当前下标 ,和 链表位置
printf("%d\n",sum);
}
Cls(H);
}
}
return 0;
}