问题C
给定一个英语词典,找出其中的所有变位词的集合。例如,“pots”、“stop”和“tops”互为变位词,因为每一个单词都可以通过改变其他单词中的字母的顺序来得到。
解答:
最容易想到解决方法就是:对于每一个单词,找出其的所有排列,然后对词典进行遍历,如果其排序在词典中,那么此排序序列就是该词典中此单词的变位词。
但是这种方法对于单词长度不是很长,且词典不是很大的时候,效率比较好;但是当单词变的很长,求其各个排列的时间、以及进行检索的时间将会很长,这种情况下,该方法不可取。
那么,有没有一种比较效率比较高的方法呢?
《编程珠玑》中给出一种效率比较高的方法,具体思路如下所示。
(1)为每个单词生成一个标签,即对每个单词按字母序进行排序,这样使所有的变位词会有相同的标签;
(2)根据标签对单词进行汇合,每个标签对应一个集合,这个集合包括其所有的变位词;
每个单词的标签的生成:如上面所叙述的那样,把这个单词所包含的字母,按照字母序进行排序。这就可以使所有的变位词的标签就全相等了。
下面是我实现这个程序的详细过程,记录下来,以进行交流和学习。
(1)词典的获取
为了获取词典,从网上随意的下载了一篇英语文章,然后进行相应的处理,从而获取了词典。
在对文章进行处理的过程中,这里去除了标点符号等简单字符,同时也进行了去除重复。
从网上获取的文章如下所示。

(2)获取“标签 单词”
通过对获取的文章进行处理,去除掉标点符号等以及去除重复过,然后对各个单词进行排序,进而获取了相应单词的“标签”,我们把标签和单词以“标签 单词”的格式保存到文件中。
保存内容如下所示。

(3)获取变位词集合
获取变位词集合的方法同《编程珠玑》上讲述的类似,获取的内容如下所示。

完成的程序代码如下所示。
-
/*
-
* Author:梦醒潇湘
-
* Date :2013/6/9/19:55
-
* Place :Hit
-
* Email :9974771**@qq.com
-
*/
-
#include <iostream>
-
#include <set>
-
#include <stdio.h>
-
#include <sys/stat.h>
-
#include <fstream>
-
#include <map>
-
-
using namespace std;
-
-
#define SOURCEFILE "big.txt" //原文件,就是小说的一部分,为了抽取单词
-
#define DESTFILE "dict.txt" //形成的词典
标签 单词
-
#define RESULTFILE "result.txt" //结果文件
-
#define MAXNUM 100 //单词的最大长度
-
#define DEBUG
-
-
set<string> dict; //保存处理好的字典
-
-
//需要删除的字符
-
const char delim[] = ".,:;`'/"+-_(){}[]<>*&^%$#@!?~/|=1234567890
tn";
-
-
/*
-
* 函数功能:将字符串中的字符串全部转化为小写
-
* 返回值 :转换后的字符串指针
-
* 参数 :
-
* @prama *word 指向源字符串的指针
-
*/
-
static char *strtolower(char *word)
-
{
-
char *s;
-
if(word == NULL)
-
{
-
return NULL;
-
}
-
for(s = word; *s != ''; s++)
-
{
-
*s = tolower(*s);
-
}
-
-
return word;
-
}
-
-
/*
-
* 函数功能:读取文件中的关键字
-
* 返回值 :转化成功返回1;反之,返回0
-
* 参数 :
-
* @prama 无
-
*/
-
static int read_file()
-
{
-
char *file, *word, *w;
-
FILE *fp = fopen(SOURCEFILE, "r");
-
struct stat sb;
-
-
if(!fp)
-
{
-
return 0;
-
}
-
-
if(stat(SOURCEFILE, &sb))
-
{
-
return 0;
-
}
-
-
file = (char *)malloc(sb.st_size);
-
if(!file)
-
{
-
fclose(fp);
-
return 0;
-
}
-
-
fread(file, sizeof(char), sb.st_size, fp);
-
-
word = strtok(file, delim);
-
while(word != NULL)
-
{
-
w = strtolower(strdup(word));
-
-
string str = w;
-
dict.insert(str);
-
-
word = strtok(NULL, delim);
-
}
-
-
free(file);
-
fclose(fp);
-
-
return 1;
-
}
-
-
/*
-
* 函数功能:用于qsort()函数
-
*/
-
int comp(const void *a, const void *b)
-
{
-
return *(char *)a - *(char *)b;
-
}
-
-
/*
-
* 函数功能:将字典中的单词保存到文件中, 并且把标签给求解出来
-
* 返回值 :保存成功,返1;反之,则返回0
-
* 参数 :
-
* @prama 无
-
*
-
* 保存格式:标签 单词
-
* 标签 单词
-
* .... ....
-
*/
-
int SaveToFile()
-
{
-
FILE *out;
-
out = fopen(DESTFILE, "w");
-
if(out == NULL)
-
{
-
cout << "fopen() error in SaveToFile()."
<< endl;
-
return 0;
-
}
-
-
set::iterator iter = dict.begin();
-
for( ; iter != dict.end(); iter++)
-
{
-
char tmpone[MAXNUM] = {''};
-
char tmptwo[MAXNUM] = {''};
-
-
strncpy(tmpone, (*iter).c_str(), MAXNUM);
-
strncpy(tmptwo, (*iter).c_str(), MAXNUM);
-
-
qsort(tmpone, strlen(tmpone), sizeof(char), comp);
-
-
#ifdef DEBUG
-
cout << tmpone << " "<< *iter << endl;
-
#endif
-
-
fprintf(out, "%s %sn",
tmpone, tmptwo);
-
}
-
-
fclose(out);
-
-
cout << "字典保存到文件成功."
<< endl;
-
return 1;
-
}
-
-
/*
-
* 函数功能:读取保存好的字典文件,进行压缩,获取最终的结果
-
* 返回值 :读取成功,返回1;反之,返回0
-
* 参数 :
-
* @prama 无
-
*/
-
int squasd()
-
{
-
/*
-
ifstream infile(DESTFILE, ios::in);
-
ofstream outfile("Result.txt",ios::out);
-
//assert(infile);
-
//assert(outfile);
-
if(infile == NULL || outfile == NULL)
-
{
-
return 0;
-
}
-
-
string sig, word;
-
string sigone, wordone;
-
infile >> sig >> word;
-
outfile << sig << " " << word;
-
while(infile >> sigone >> wordone)
-
{
-
if(strcmp(sigone.c_str(), sig.c_str()) == 0)
-
{
-
if(strcmp(wordone.c_str(), word.c_str()) == 0)
-
{
-
//the same word
-
continue;
-
}
-
else
-
{
-
outfile << " " << wordone;
-
}
-
}
-
else
-
{
-
outfile << endl;
-
outfile << sigone << " " << wordone;
-
sig = sigone;
-
word = wordone;
-
}
-
}
-
infile.close();
-
outfile.close();
-
cout << "处理完毕."
<< endl;
-
return 1;
-
*/
-
//打开dict.txt文件
-
ifstream infile(DESTFILE, ios::in);
-
if(infile == NULL)
-
{
-
return 0;
-
}
-
-
//读取文件内容,保存到multimap中
-
multimap res;
-
string sig, word;
-
while(infile >> sig >> word)
-
{
-
res.insert(make_pair(sig, word));
-
}
-
-
//打开保存最终结果的文件
-
ofstream outfile(RESULTFILE, ios::out);
-
if(outfile == NULL)
-
{
-
return 0;
-
}
-
-
//进行处理
-
multimap::iterator iter = res.begin();
-
if(iter == res.end())
-
{
-
return 0;
-
}
-
outfile << iter->first << " " << iter->second;
-
iter++;
-
-
sig = iter->first;
-
word = iter->second;
-
-
for( ; iter != res.end(); iter++)
-
{
-
char tmpone[MAXNUM] = {''};
-
char tmptwo[MAXNUM] = {''};
-
-
strncpy(tmpone, (iter->first).c_str(), MAXNUM);
-
strncpy(tmptwo, (iter->second).c_str(), MAXNUM);
-
-
if(strcmp(sig.c_str(), tmpone) == 0)
-
{
-
if(strcmp(word.c_str(), tmptwo) == 0)
-
{
-
//same word here
-
continue;
-
}
-
else
-
{
-
outfile << " " << tmptwo;
-
}
-
}
-
else
-
{
-
outfile << endl;
- outfile << tmpone << " " << tmptwo;
-
sig = tmpone;
-
word = tmptwo;
-
}
-
}
-
infile.close();
-
outfile.close();
- }
- int main()
- {
-
//读取文件,创建词典
-
if(!read_file())
-
{
-
return EXIT_FAILURE;
-
}
-
//保存字典到文件中
-
if(!SaveToFile())
-
{
-
return EXIT_FAILURE;
-
}
-
//进行最后结果的出来
-
if(!squasd())
-
{
-
return EXIT_FAILURE:
-
}
-
return EXIT_SUCCESS;
- }
- //上面的代码在粘贴的时候可能会有错误,附件为文件。
链接:http://blog.chinaunix.net/uid-26548237-id-3761073.html
本文介绍了一种高效查找英语词典中变位词的方法,通过为每个单词生成一个由其字母按顺序排列组成的标签,相同标签的单词即为变位词。并提供了一个具体的实现程序。
1266

被折叠的 条评论
为什么被折叠?



