查找兄弟单词

题目描述:

实现一个可存储若干个单词的字典。用户可以:

在字典中加入单词。查找指定单词在字典中的兄弟单词个数。查找指定单词的指定序号的兄弟单词,指定序号指字典中兄弟单词按字典顺序(参见Page 3)排序后的序号(从1开始)

清空字典中所有单词。

定义 格式说明

单词由小写英文字母组成,不含其它字符。兄弟单词给定一个单词X,如果通过任意交换单词中字母的位置得到不同的单词Y,那么定义Y是X的兄弟单词。字典顺序   两个单词(字母按照自左向右顺序),先以第一个字母作为排序的基准,如果第一个字母相同,就用第二个字母为基准,如果第二个字母相同就以第三个字母为基准。依此类推,如果到某个字母不相同,字母顺序在前的那个单词顺序在前。如果短单词是长单词从首字母开始连续的一部分,短单词顺序在前。举例:bca是abc的兄弟单词;abc与abc是相同单词,不是兄弟单词

/******************************************************************************

  Copyright (C), 2001-2012, Huawei Tech. Co., Ltd.

 ******************************************************************************
  File Name     : FindSimilarWord.cpp
  Version       :
  Author        :littlerock
  Created       : 2014/03
  Last Modified :
  Description   :
  Function List :

  History       :
  1.Date        : 2014/03
    Author      :
    Modification: Created file

******************************************************************************/
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cctype>
#include <iostream>
#include <set>
#include <map>
using namespace std;
const unsigned int prim_num[26] = {2, 3, 5, 7, 11, 13, 17,
						  19, 23, 29, 31, 37, 41, 43,
						  47, 53, 59, 61, 67, 71,
						  73, 79, 83, 89, 97, 101};

map<unsigned int, set<string> > dict;

bool isWord(char* word){
	while(*word != '\0' && isalpha(*word) && islower(*word)) 
		word++;
	if(*word == '\0')
		return true;
	else
		return false;
}
unsigned int getNum(char *word){
	unsigned int result = 1;
	char* p = word;
	while(*p != '\0'){
		result = result*prim_num[(*p-'a')];
		p++;
	}
	return result;
}
/******************************************************************************
原    型:int AddOneWord (char* Word);
功    能:在字典中增加一个单词
输入参数: 
          Word 单词字符串,调用者保证Word指针不为空,指向的是合法单词
输出参数:
          无
返回值:
        -1 失败(单词在字典中已存在等情况)
        0  成功
********************************************************************************/
int AddOneWord (char* Word)
{
	if(!Word || *Word == '\0' || !isWord(Word))
		return -1;

	unsigned int num = getNum(Word);
	string str(Word);
	if(dict[num].count(str) == 0){
		dict[num].insert(str);
		return 0;
	}
	else{
		return -1;
	}
}

/******************************************************************************
原    型:int FindSimilarWordNum (char* Word);
功    能:查找指定单词在字典中的兄弟单词个数
输入参数:
          Word 指定单词字符串,调用者保证Word指针不为空,指向的是合法单词
输出参数:
          无
返回值:
          返回指定单词在字典中的兄弟单词总个数。如果不存在兄弟单词,返回0
*******************************************************************************/
int FindSimilarWordNum (char* Word)
{
	if(!Word || *Word == '\0' || !isWord(Word))
		return 0;
	unsigned int num = getNum(Word);
	if(dict[num].size() == 0)
		return 0;
	else{
		set<string> word_list = dict[num];
		string str(Word);
		if(word_list.count(str) != 0){
			return word_list.size() - 1;
		}else{
			return word_list.size();
		}
	}
}

/******************************************************************************
原    型:int FindOneSimilarWord (char* Word, int Seq, char* SimilarWord);
功    能:查找指定单词的指定序号的兄弟单词,指定序号指字典中兄弟单词按字典顺序
          排序后的序号(从1开始)
输入参数:
          Word 指定单词字符串,调用者保证Word指针不为空,指向的是合法单词
          Seq 指定序号(大于等于1)
输出参数:
          SimilarWord 返回兄弟单词字符串,指针不为空,指向的内存由调用者预先分配,
          占51个字节长度,输出的兄弟单词必须紧跟’\0’结束。如果不存在指定序号的
          兄弟单词,输出空串。
返回值:
          -1 失败(如果不存在指定序号的兄弟单词,返回失败)
          0  成功
*******************************************************************************/
int FindOneSimilarWord (char* Word, int Seq, char* SimilarWord)
{
	if(!Word || *Word == '\0' || !isWord(Word) || !SimilarWord || Seq <= 0 ){
		*SimilarWord = '\0';
		return -1;
	}
	unsigned int num = getNum(Word);
	string str(Word);
	if(dict.find(num) == dict.end()){
		memcpy(SimilarWord, "", 51);
		return -1;
	}
	else{
		set<string> word_list = dict[num];
		word_list.erase(str);
		if(Seq > word_list.size()){
			memcpy(SimilarWord, "", 51);
			return -1;
		}else{
			vector<string> tmp_vec(word_list.begin(), word_list.end());
			sort(tmp_vec.begin(), tmp_vec.end());
			char *p = const_cast<char*>(tmp_vec.at(Seq - 1).c_str());
			memcpy(SimilarWord, p, 51);
			return 0;
		}
	}
}

/******************************************************************************
原    型:void ClearAllWords(void);
功    能:清空字典中所有单词
输入参数: 
          无
输出参数:
          无
返回值:
          无

*******************************************************************************/
void ClearAllWords(void)
{
	if(!dict.empty()){
		map<unsigned int, set<string> >().swap(dict);
	}
}

总结:
1、OJ只支持vs2005。所以使用unordered_map的想法被迫放弃,能选择的只有stl中的map容器了,但是查找插入的的效率肯定要低很多。
2、对于map中的unsigned int 这块用到了一个数学定理:
任何一个大于1的自然数N,都可以唯一分解成有限个质数的乘积 N=(P_1^a1)*(P_2^a2)......(P_n^an) , 这里P_1<P_2<...<P_n是质数,其诸方幂 ai 是正整数。
这样的分解称为N 的标准分解式。
算术基本定理的内容由两部分构成:分解的存在性、分解的唯一性(即若不考虑排列的顺序,正整数分解为素数乘积的方式是唯一的)。
算术基本定理是初等数论中一个基本的定理,也是许多其他定理的逻辑支撑点和出发点。
此定理可推广至更一般的交换代数和代数数论。高斯证明复整数环Z[i]也有唯一分解定理。它也诱导了诸如唯一分解整环,欧几里得整环等等概念。 更一般的还有戴德金理想分解定理。

为每一个字母分配一个标准的素数值,则兄弟单词中的字母对应的素数的乘积肯定是相同的,而且不同的单词乘积肯定不同。
3、set中遍历的顺序,并不能严格的按照字母表顺序来排列,而且set不支持sort排序,只能重新拷贝到vector中再进行排序。
4、空间释放,没有简单的使用clear而是使用了swap。



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值