编程珠玑中关于一个单词的所有变位词的解决

本文详细阐述了一种高效查找变位词的方法,通过为单词设置独特的标签来简化搜索过程。利用C++实现,展示如何通过统计字母频率并结合数字编码形成唯一标识符。同时介绍了排序算法的应用,并提供了代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        最近在阅读编程珠玑,真是一本爱不释手的好书啊,对于实际编程中经常遇到的问题,引导读者去思考,去寻找最佳的解决方案。

废话不多说。问题描述如下:

       给定一本英语单词词典请找出一个给定单词的所有变位词。例如“dog”这个单词,它的变位词可能有“dgo”,“ogd”,“god”等几个。书中给出的解决方案是给每个单词配一个标签。例如“dog”的吧标签是"d1g1o1",思想就是统计每个字母出现的次数。例如单词“totto”,那么它的标签是"t3o2",这样如果两个单词是变位词,那么他们的标签是一样的。

       总结一下,我们需要做的是三件事。

       1.对字典中的所有单词设置标签。

       2.对字典中的字按照他们的标签排序。

       3.对指定的单词实现变位词查找

       代码如下:代码使用c++,编译环境是vs2010,可能代码中有不少用到stl知识的,看不懂的请自行脑补。

// 问题描述,给定一本字典和一个单词,找出字典中所有这个单词的变形体.如dog,如果字典中出现dgo,odg,等,那么符合查找条件
//1.为字典中字符串的每个单词设置签名,具有相同变形体的字符串的签名相同
//2.对所有字符串按照签名字典排序,在签名相同的情况下,按照字符串本身排序.
//问题来自编程珠玑第二章第一个问题,。查找效率一定要关注!计划两个小时完成。。。。
//yoghurt2014/7/26 武汉大学
//花了一个小时,实验成功单个单词的变形体索引。加上一个简单的循环,可以实现数组中所有的字符串
// 明天完成按照变形体索引排序。
//熟悉一下list下排序算法的使用。
#include<iostream>
#include <algorithm>
#include <vector>
#include <list>                                  
#include <string>
#include <iterator>
using namespace std;
const int maxamount = 10000;
struct directionary{							//定义一个结构体                
	string word;								//单词本身
	string wordindex;							//单词变形体编号
};

directionary findstring;                       //需要查找的单词,这里为了程序方便,我使用了结构体
bool sort_by_wordindex(const directionary *d1,const directionary *d2)    //根据单词变形体编号排序
{
   return d1->wordindex < d2->wordindex;
}
bool findwordindex(const directionary *d)                              //在字典中寻找和指定单词相同的单词变形体
{
	return d->wordindex == findstring.wordindex;
}
void computewordindex(directionary &s)                                //计算单词的变形体编号,如“dog”,则变形体为“d1g1o1”
{  
	int array26[26] = {0};                                            //每个单词中字母出现的次数初始化为0
	for (int i = 0; i < s.word.length();++i){                         //统计单词中每个字母出现的次数
		char c = s.word[i];
		array26[int(c-'a')] ++;
	}
	int num = 0;
	for (int i = 0 ;i < 26;++i){                                      //统计不一样字母的个数
		if (array26[i])
			num++;
	}
	s.wordindex.resize(num*2);                                        //为变位词开辟存储空间

	int n = 0;
	for (int i = 0;i < 26;++i){                                
		if (array26[i]){

			//cout << char(i+'a');
			s.wordindex[n++] = char(i+'a');                          //把字母字符给变位词复制
			//cout << array26[i];
			s.wordindex[n++] = char(array26[i]+48);                  //把数字字符给变位词复制

		}
	}

}


int main()
{
	int array26[26] = {0};            //代表一个字符串中每个出现的次数 如dogg,那么
	directionary *d = new directionary[maxamount];             //初始化的字典中,有10000个单词,这差不多一般字典只有这么多了
	d[0].word = "dog";
	d[1].word = "odg";
	d[2].word = "god";
	d[3].word = "ogd";
	for (int i = 4;i < maxamount;++i){
		d[i].word = "jiajia";
	}
	d[800].word = "dgo";
	//把元素装进list中啊。
	list<directionary*>l;                                       //这里我选择的容器list,好吧,我觉得最好的set,或者map容器,可以实现实现对数查找
	for (int i = 0;i < maxamount;++i){
		l.push_back(&d[i]);
	}
	list<directionary*>::iterator liteator;

	for(liteator = l.begin();liteator !=l.end();++liteator){

		for (int k = 0;k < 26;++k){
			array26[k] = 0;
		}

		for (int i = 0; i < (*liteator)->word.length();++i){
			char c = (*liteator)->word[i];
			array26[int(c-'a')] ++;
		}
		int num = 0;
		for (int i = 0 ;i < 26;++i){
			if (array26[i])
				num++;
		}
		(*liteator)->wordindex.resize(num*2);
	
		int n = 0;
		for (int i = 0;i < 26;++i){
			if (array26[i]){

				//cout << char(i+'a');
				(*liteator)->wordindex[n++] = char(i+'a');
				//cout << array26[i];
				(*liteator)->wordindex[n++] = char(array26[i]+48);
			}
		}
	}

	
	//最后一步,实现对单个输入单词的所有变形词的查找.
	cout << "input the string you want to find:";
	cin >> findstring.word;
	//计算这个单词的变形体。
	computewordindex(findstring);
	liteator = find_if(l.begin(),l.end(),findwordindex);
	while(liteator!=l.end())
	{
		if ((*liteator)->word != findstring.word){                             //同义词应该不包括自己。。。。
			cout << "和"  << findstring.word << "属于同义词的单词有:" << (*liteator)->word << endl;
		}

		liteator = find_if(++liteator,l.end(),findwordindex);                   //进行下一轮迭代.
		
	}

	delete []d;
	return 0;
}

      代码中的不足时应该使用set或者map容器的,因为这些容器自带的find函数,可以实现对数时间的查找,效率更高!!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值