变位词实现

问题描述

(来源于《编程珠玑》第2版的第2章第11页问题 C

Given a dictionary of english words,find all sets of anagrams,For instance, “posts”,”stop”and ”tops” are all anagrams of one another because each can be formed by permuting the letters of the others.[译] 给定一个英语字典,找出其中的所有变位词集合。例如,“pots”、“stop”和“tops”互为变位词,因为每一个单词都可以通过改变其他单词中字母的顺序来得到。

方案一

按照书上给出的解法,先对每一个单词生成相应的“签名”(“signature”),即把单词中的字母按照字母表的顺序重新排列,例如stop 重新排列成opst , 然后把有相同signature的单词归为一组输出。基本过程如下:

变位词实现_第1张图片

其中sign()函数用于生成每一个单词的”签名“,如何生成呢?由于每个单词的长度一般都很短(不超过10个字母)于是可选择用直接插入排序法。其他的数据结构和函数很简单,直接看代码吧!

代码:

#include<stdio.h>
#include<string.h>
 
#define MAX_WORD  100 /* the max length of a word */
#define MAX_NUM   100 /* the max number of words in a dictionary */
 
struct Word{
 char ch[MAX_WORD];/*a word*/
 char sig[MAX_WORD];/*signature*/
 int flag;/*has been print or not*/
};
struct Word dic[MAX_NUM];

 /*put in*/
 int  putin();
 void putout(int count);
/*generate a word’s signature */
void sign(int count);
void insertSort(char * arr,int left,int right);

 /* main() */
int main(void){
     int count;
     int i;
     count=putin();
     sign(count);
     putout(count);
     return 0;
 }

int putin() {
     int c=0;
     while(scanf(“%s”,dic[c].ch)!=EOF)
     {
         strcpy(dic[c].sig,dic[c].ch);
         dic[c].flag=0;
         c++;
     }
     return c;
 }
 
 void sign(int count) {
     int cnt,i,len;
     for(cnt=0;cnt<count;cnt++)
     {
         len=strlen(dic[cnt].ch);
         insertSort(dic[cnt].sig,0,len);
         dic[cnt].sig[len]=‘\0′;
     }
 }

 void insertSort (char * arr,int left,int right){
     int i,j;
     char temp;
     for(i=left+1;i<right;i++){
         if(arr[i-1]>arr[i]){
             temp=arr[i];
             j=i-1;
            do{
                arr[j+1]=arr[j];
                j–;
            }while(j>=left && arr[j]<temp);
            arr[j+1]=temp;
         }
     }
 }/* insertSort */
 
void putout(int cnt) {
     int i,j;
 
    for(i=0;i<cnt;i++){
        if(dic[i].flag==0){
            printf(“———-%s———-\n“,dic[i].sig);
            printf(“%s\n“,dic[i].ch);
             dic[i].flag=1;

             for(j=0;j<cnt;j++){
                 if(strcmp(dic[i].sig,dic[j].sig)==0&&dic[j].flag==0){
                    dic[j].flag=1;
                    printf(“%s\n“,dic[j].ch);
                }
             }
        }
     }
 
 }

方案二

我们获得的”啊哈!灵机一动“就是标识字典中的每一个词,使得在相同变位词类中的单词具有相同的标识。然后,将所有具有相同标识的单词集中在一起。这将原始的变位词问题简化为两个子问题:选择标识和集中具有相同标识的单词。 对第一个问题,我们可以使用基于排序的标识:将单词中的字母按照字母表顺序排列。要解决第二个问题,我们将所有的单词按照其标识的顺序排列。

代码:

#include <iostream>
#include <map>
#include <string>
#include <fstream>
using namespace std;

int compare_string(const void *a,const void *b){
	return *((char*)(a)) - *((char*)(b));
}
void FindAnagram(char *file_name){
	ifstream in_file(file_name);
	string word_sort;
	string word;
	multimap<string,string> word_map;
	while(in_file>>word){
		word_sort = word;
		qsort(word_sort.begin(),word_sort.length(),sizeof(char),compare_string);
		word_map.insert(make_pair(word_sort,word));
	}
	multimap<string,string>::const_iterator iter = word_map.begin();
	multimap<string,string>::const_iterator iter_end = word_map.end();
	while(iter_end != iter){
		cout<<iter->first<<":"<<iter->second<<endl;
		++iter;
	}
}

int main(){
	FindAnagram("f://data.txt");
	return 0;
}
========================================================
转载请注明出处:http://blog.csdn.net/utimes/article/details/8760350 ========================================================

你可能感兴趣的:(变位词实现)