数据结构与算法分析 C++ 查找等长单词且只有一个元素不同的所有单词


第四版map set 实现章节(P143) 书中提到的 :编写一个程序来找出通过单个字母的替换可以变成至少15个其他的单词的单词。

如: 单词wine 可以变成dine、fine、line、nine、pine、或vine。

单词wine  可以变成wind、wing、wink、wins。


#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <iterator>

using namespace std;
/*
*	describe:
*			检测两个单词是否在一个字母上
*			如果word1 和word2 具有相同的长度
*			并且只有一个字母不同,返回true
*/
bool oneCharOff(const string & word1, const string & word2)
{
	if (word1.length() != word2.length())
		return false;
	int diffs = 0;
	for (size_t i = 0; i < word1.length(); ++i)
	{
		if (word1[i] != word2[i])
		     if (++diffs > 1)
			   return false;
	}
	return diffs == 1;
}

/*
*	describe:
*			计算map对象,其中关键字为单词,值为单词的vector
*			vector 中的这些单词只在一个字母上不同于对应的关键字
*			使用一个高效的算法,该算法用到一个map运行的时间为O(N logN)
*/
map<string, vector<string>> computeAdjacentWords(const vector<string> & words)
{
	map<string, vector<string>> adjWords;
	map<int, vector<string>> wordsByLength;
	
	/*将单词按照它们的长度分组*/
	for (auto & str : words)
		wordsByLength[str.length()].push_back(str);   /* [] 访问的是map<int,vector> int对应的值,返回的对象是vector,故可以调用push_back
													  */

		/*对每组分别处理*/
	for (auto & entry : wordsByLength)
	{
		const vector<string> & groupsWords = entry.second;
		int groupNum = entry.first;
		/* 对每组的每一个位置进行处理 */
		for (size_t i = 0; i < groupNum; ++i)
		{
			/*删除特定位置上的字母,算出代表*/
			/* 具有相同代表的单词是相邻的;填充map... */
			map<string, vector<string>> repToWord;
			for (auto & str : groupsWords)
			{
				string rep = str;
				rep.erase(i,1);
				repToWord[rep].push_back(str);
			}

			/*然后查找那些具有多个一个串的map 值*/
			for (auto & entry : repToWord)
			{
				const vector<string> & clique = entry.second;
				if(clique.size()>=2)
					for(int p=0;p<clique.size();++p)
						for (int q = p + 1; q < clique.size(); ++q)
						{
							adjWords[clique[p]].push_back(clique[q]);
							adjWords[clique[q]].push_back(clique[p]);
						}
			}
		}
	}
	
	return adjWords;
}

void printMap_str_vec(map<string, vector<string>> & mpSV)
{
	auto itr = mpSV.begin();
	for (; itr != mpSV.end(); itr++)
	{
		cout << itr->first << ": ";
		for (int i = 0; i < itr->second.size(); i++)
		{
			cout << itr->second.at(i) << "  ";

		}
		cout << endl;
	}
	cout << endl;
}

int main()
{
	string str = { "word" };
	string str1 = { "nord" };
	cout << oneCharOff(str, str1) << endl;
	/*单词不能重复,如果处理文本单词,最好先用set 去重*/
	vector<string> vec = { "ine","dine","wine","nine","mine","vine","pine","line" };
	vector<string> vec1 = {"boot","mine","hoot","wak","lot","los","lof","soot","zoo","zoot","wat"};
	vector<string> vec2 = {"wine","dine","fine","line","mine","vine",
						   "wind","wing","wink","wins"};
	map<string, vector<string>> mpc, mpc1,mpc2;

	mpc = computeAdjacentWords(vec);
	mpc1 = computeAdjacentWords(vec1);
	mpc2 = computeAdjacentWords(vec2);

	printMap_str_vec(mpc);
	printMap_str_vec(mpc1);
	cout << "\n Test  vec2: " << endl;
	printMap_str_vec(mpc2);


	return 0;


}


Test vec2测试结果:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值