Mr. Right有一个奇怪的嗜好,就是看见一个单词就有找它所有的变位词的冲动。一个单词的变位词就是该单词所有字母的一个排列。
对应Mr. Right看到的每个单词,输出落在字典里的它的变位词的个数。
//如果用普通的方法,一个一个比较的话,当输入的单词很大的时候,时间是无法忍受的
//我看到这一道题目的印象是将字符串通过某种算法生成一个整数,但我没有想到一个好的办法
//尝试了很多种都出错,因为数组的长度有限,所以生成的整数不能太大
//后来我模仿hash表的算法,设计了这样一个算法
//英文字母有26个,int整形有32位,当字符串有包含某个字母时就把相应的位设置为1
//如abcd 则1,2,3,4位被设置为1
//考虑到,会生成相同的整数,而且我把有重复字母的串如:abcd 和 aabcd 都生成同一个整数
//因为一个bit只能代表有或者没有,不能表示字母的个数
//因此我在每个数的入口都挂了一个链表,把有相同整数而字符串不同的放在一张链表上
//程式如下:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define MAX 90000
typedef struct link
{
int date;
char string[10];
struct link* next;
}*plink;
struct link hashtable[90000];
void HashString(char *str)
{
int ch=0;
char *p=str;
plink s,pl;
while(*p!='/0')
{
ch = ch | ( 1<<(*p - 'a'));
p++;
}
ch = ch%MAX;
if(hashtable[ch].date==0)
{
hashtable[ch].date++;
strcpy(hashtable[ch].string,str);
}
else
{
if(strcmp(hashtable[ch].string,str)==0)
{
hashtable[ch].date++;
}
else
{
pl=&hashtable[ch];
s=hashtable[ch].next;
while(s!=NULL)
{
if(strcmp(s->string,str)==0)
{
s->date++;
break;
}
pl=s;
s = s->next;
}
if(s==NULL)
{
s = (plink)malloc(sizeof(struct link));
pl->next = s;
s->date=1;
strcpy(s->string,str);
s->next=NULL;
}
}
}
}
void turn (char *str)
{
int n=strlen(str),i,j,k;
char *s=str,c,tmp;
for(i=0;i<n;i++)
{
c=s[0];k=0;
for(j=1;j<n-i;j++)
{
if(c<s[j])
{c=s[j];k=j;}
}
tmp=s[n-i-1];
s[n-i-1]=c;
s[k]=tmp;
}
}
int HashCout(char* string)
{
int ch=0;
char *p=string;
plink s;
while(*p!='/0')
{
ch = ch | ( 1<<(*p - 'a'));
p++;
}
ch = ch%MAX;
if(hashtable[ch].date!=0)
{
if(strcmp(hashtable[ch].string,string)==0)
return hashtable[ch].date;
else
{
s = hashtable[ch].next;
while(s!=NULL)
{
if(strcmp(s->string,string)==0)
{
return s->date;
}
s = s->next;
}
}
}
return 0;
}
int main()
{
char string[10];
int n,m;
scanf("%d",&n);
getchar();
while(n-->0)
{
gets(string);
turn(string);
HashString(string);
}
scanf("%d",&m);
getchar();
while(m-->0)
{
gets(string);
turn(string);
printf("%d/n",HashCout(string));
}
return 0;
}
//该程式并没有释放链表的结点,所以可以再改进一下
//原题在http://acm.fzu.edu.cn/problem.php?pid=1410
//我的算法到目前为止用的时间最少0.16秒 ^_^
输入输出格式
输入数据第一行为一个整数n,1<=n<=10^5,之后n行每行只包含一个单词,不含词组。这些单词构成了Mr. Right的字典。每个单词长度不大于9个字母。接着一行为一个整数m,1<=m<=100,表示Mr. Right将看见的单词数。之后m行每行包含一个单词。(题目中出现的每个单词都只由小写字母组成)对应Mr. Right看到的每个单词,输出落在字典里的它的变位词的个数。
//如果用普通的方法,一个一个比较的话,当输入的单词很大的时候,时间是无法忍受的
//我看到这一道题目的印象是将字符串通过某种算法生成一个整数,但我没有想到一个好的办法
//尝试了很多种都出错,因为数组的长度有限,所以生成的整数不能太大
//后来我模仿hash表的算法,设计了这样一个算法
//英文字母有26个,int整形有32位,当字符串有包含某个字母时就把相应的位设置为1
//如abcd 则1,2,3,4位被设置为1
//考虑到,会生成相同的整数,而且我把有重复字母的串如:abcd 和 aabcd 都生成同一个整数
//因为一个bit只能代表有或者没有,不能表示字母的个数
//因此我在每个数的入口都挂了一个链表,把有相同整数而字符串不同的放在一张链表上
//程式如下:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define MAX 90000
typedef struct link
{
int date;
char string[10];
struct link* next;
}*plink;
struct link hashtable[90000];
void HashString(char *str)
{
int ch=0;
char *p=str;
plink s,pl;
while(*p!='/0')
{
ch = ch | ( 1<<(*p - 'a'));
p++;
}
ch = ch%MAX;
if(hashtable[ch].date==0)
{
hashtable[ch].date++;
strcpy(hashtable[ch].string,str);
}
else
{
if(strcmp(hashtable[ch].string,str)==0)
{
hashtable[ch].date++;
}
else
{
pl=&hashtable[ch];
s=hashtable[ch].next;
while(s!=NULL)
{
if(strcmp(s->string,str)==0)
{
s->date++;
break;
}
pl=s;
s = s->next;
}
if(s==NULL)
{
s = (plink)malloc(sizeof(struct link));
pl->next = s;
s->date=1;
strcpy(s->string,str);
s->next=NULL;
}
}
}
}
void turn (char *str)
{
int n=strlen(str),i,j,k;
char *s=str,c,tmp;
for(i=0;i<n;i++)
{
c=s[0];k=0;
for(j=1;j<n-i;j++)
{
if(c<s[j])
{c=s[j];k=j;}
}
tmp=s[n-i-1];
s[n-i-1]=c;
s[k]=tmp;
}
}
int HashCout(char* string)
{
int ch=0;
char *p=string;
plink s;
while(*p!='/0')
{
ch = ch | ( 1<<(*p - 'a'));
p++;
}
ch = ch%MAX;
if(hashtable[ch].date!=0)
{
if(strcmp(hashtable[ch].string,string)==0)
return hashtable[ch].date;
else
{
s = hashtable[ch].next;
while(s!=NULL)
{
if(strcmp(s->string,string)==0)
{
return s->date;
}
s = s->next;
}
}
}
return 0;
}
int main()
{
char string[10];
int n,m;
scanf("%d",&n);
getchar();
while(n-->0)
{
gets(string);
turn(string);
HashString(string);
}
scanf("%d",&m);
getchar();
while(m-->0)
{
gets(string);
turn(string);
printf("%d/n",HashCout(string));
}
return 0;
}
//该程式并没有释放链表的结点,所以可以再改进一下
//原题在http://acm.fzu.edu.cn/problem.php?pid=1410
//我的算法到目前为止用的时间最少0.16秒 ^_^