找到一个单词的所有相似单词

相似单词为 只差一位字母的单词,练习Map容器

package chapter4;

import java.util.*;
import java.util.Map.Entry;

/*
 * 说明:找到一个单词的所有相似单词 例如: wine 和 dine wind 和wing 只有一个字母不同
 */
public class TreeMapTest {

	/*
	 * 判断2个单词是否指差一个字母
	 */
	public static boolean oneCharOff(String s1, String s2) {
		if (s1.length() != s2.length())
			return false;
		int diff = 0;
		for (int i = 0; i < s1.length() - 1; i++) {
			if (s1.charAt(i) != s2.charAt(i))
				diff++;
			if (diff > 1)
				return false;
		}

		return diff == 1;
	}

	/*
	 * 打印方法
	 */
	public static void print(Map<String, List<String>> map) {
		for (Map.Entry<String, List<String>> entry : map.entrySet()) {
			List<String> words = entry.getValue();
			System.out.print(entry.getKey() + ":");
			for (int i = 0; i < words.size(); i++) {
				System.out.print(words.get(i) + " ");
			}
			System.out.println();
		}
	}

	/**
	 * 方法名:computeWords 说明:方法1
	 */
	public static Map<String, List<String>> computeWords1(List<String> words) {

		Map<String, List<String>> map = new TreeMap<String, List<String>>();
		String[] word = new String[words.size()];
		words.toArray(word);
		for (int i = 0; i < word.length; i++) {
			for (int j = i + 1; j < word.length; j++) {
				if (oneCharOff(word[i], word[j])) {
					update(map, word[i], word[j]);// 互为相似单词
					update(map, word[j], word[i]);
				}
			}
		}

		return map;
	}

	/**
	 * 方法名:update 说明:更新
	 */
	private static <KeyType> void update(Map<KeyType, List<String>> map,
			KeyType key, String s) {
		List<String> words = map.get(key);
		if (words == null) {
			words = new ArrayList<String>();
			map.put(key, words);
		}
		words.add(s);
	}

	/**
	 * 方法名:groupByLength 说明:先将给的单词按照长度分组
	 */
	private static Map<Integer, List<String>> groupByLength(List<String> words) {
		Map<Integer, List<String>> map = new TreeMap<Integer, List<String>>();
		for (String s : words)
			update(map, s.length(), s);
		return map;
	}

	/**
	 * 方法名:computeWord 说明:方法2
	 */
	public static Map<String, List<String>> computeWords2(List<String> words) {

		Map<String, List<String>> map = new TreeMap<String, List<String>>();

		for (Entry<Integer, List<String>> entry : groupByLength(words)
				.entrySet()) {
			String[] word = new String[entry.getValue().size()];
			entry.getValue().toArray(word);
			for (int i = 0; i < word.length; i++) {
				for (int j = i + 1; j < word.length; j++) {
					if (oneCharOff(word[i], word[j])) {
						update(map, word[i], word[j]);// 互为相似单词
						update(map, word[j], word[i]);
					}
				}
			}
		}
		return map;

	}

	/**
	 * 方法名:computeWords3
	 * 说明:该方法效率最高。首先也是按照长度分组,分组完了之后,对每组分别做以下操作:
	 * 1:从头到尾分别去掉每个单词的一位字母。将剩下的作为一个键,该单词作为值 放到新建的
	 * map<String,List<String>>reToWord里
	 * 2:遍历reToWord,找到size>=2的,(因为只有>=2的 才代表含有相似的)例如wine和wane 当去掉第2位
	 * 时,首先wine会进List,wane匹配到了wne也会进去,所以是2个
	 */
	public static Map<String, List<String>> computeWords3(List<String> words) {

		Map<String, List<String>> adjWords = new TreeMap<String, List<String>>();
		Map<Integer, List<String>> wordsByLength = new TreeMap<Integer, List<String>>();
		for (String w : words)
			update(wordsByLength, w.length(), w);

		for (Map.Entry<Integer, List<String>> entry : wordsByLength.entrySet()) {
			List<String> groupsWords = entry.getValue();
			int groupNum = entry.getKey();
			for (int i = 0; i < groupNum; i++) {
				Map<String, List<String>> repToWord = new TreeMap<String, List<String>>();
				for (String str : groupsWords) {
					String rep = str.substring(0, i) + str.substring(i + 1);
					update(repToWord, rep, str);
				}
				for (List<String> wordClique : repToWord.values())
					if (wordClique.size() >= 2)
						for (String s1 : wordClique)
							for (String s2 : wordClique)
								if (s1 != s2)
									update(adjWords, s1, s2);
			}
		}
		return adjWords;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<String> list = new ArrayList<String>();
		list.add("wane");
		list.add("wine");
		list.add("aine");
		list.add("dine");
		list.add("anew");
		list.add("kine");
		list.add("qine");
		list.add("eine");
		list.add("rine");

		print(computeWords1(list));
		System.out.println();
		print(computeWords2(list));
		System.out.println();
		print(computeWords3(list));
	}

}
时间: 2024-08-10 02:11:29

找到一个单词的所有相似单词的相关文章

第六章第一个Linux驱动程序:统计单词个数

第六章介绍如何在多种平台,使用多种方法测试Linux驱动. 本章主讲统计单词个数的算法的实现技术:Linux驱动.统计单词个数的功能是封装在Linux驱动中的.驱动不一定是直接和硬件打交道的,还可以喝普通的library一样提供其他程序的调用来实现特定功能的. 第一节Linux驱动到底是个什么东西 Linux驱动和普通的Linux API没有本质上的区别,只是使用Linux驱动的方式和使用Linux API的方法不同. Linux系统将每一个驱动都映射成一个文件,这些文件称为设备文件或驱动文件,

第六章 第一个Linux驱动程序:统计单词个数

在本章将进入了最令人激动的时刻,为了是读者在刚开始学习Linux驱动开发时充满期待,没有只提供Helloworld程序. 首先介绍Linux驱动到底是个什么东西,它和我们以前接触过的windows类型差不多,但是操作和工作方式有很大的区别,Linux系统将每一个驱动都映射成一个文件.这些文件成为设备文件或这驱动文件,都保存在/dev目录中. 接下来给出编写Linux驱动程序的步骤:第一步:建立Linux驱动骨架,Linux驱动程序中需要提供两个函数来分别处理驱动初始化和退出的工作.这两个函数分别

六、第一个Linux驱动程序:统计单词个数 ——学习笔记

第6章 第一个Linux驱动程序:统计单词个数 ——学习笔记 一.首先了解一下: 打印机驱动写入数据:对于打印机驱动来说,需要接收这些被写入的数据,并将它们通过PC的并口.USB等端口发送给打印机.要实现这一过程就需要Linux驱动可以响应应用程序传递过来的数据.这就是Linux驱动的事件,虽然在C语言里没有事件的概念,但却有与事件类似的概念,这就是回调(callback)函数.因此,编写Linux驱动最重要的一步就是编写回调函数,否则与设备文件交互的数据将无法得到处理.图6-1是应用软件.设备

第六章、第一个linux驱动程序:统计单词个数 读书笔记

第六章.第一个linux驱动程序:统计单词个数 一.编写Linux驱动程序的步骤 1.建立Linux驱动骨架(装载和卸载Linux驱动) Module_init处理驱动初始化,module_exit处理驱动退出 2.注册和注销设备文件 Misc_register函数创建和misc_deregister移除设备文件 3.指定与驱动相关的信息 modinfo 4.指定回调函数 5.编写业务逻辑 6.编写makefile文件 7.编译Linux驱动程序 8.安装和卸载Linux驱动 二.Linux驱动

一个mapreduce得到需要计算单词概率的基础数据

第一步,先计算需要计算概率的词频,单词种类数,类别单词总数(类别均是按照文件夹名区分)(基础数据以及分词了,每个单词一行,以及预处理好) package org.lukey.hadoop.classifyBayes; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.uti

HW—字符串最后一个单词的长度,单词以空格隔开。

描述 计算字符串最后一个单词的长度,单词以空格隔开. 知识点 字符串,循环 运行时间限制 0M 内存限制 0 输入 一行字符串,长度小于128. 输出 整数N,最后一个单词的长度. 样例输入 hello world 样例输出 5 测试OK代码: import java.util.Scanner; public class Main{ public static void main(String[] args) { int i; // System.out.println("请输入字符串:&quo

Android深度探索(卷1)HAL与驱动开发 第六章 第一个Linux驱动程序:统计单词个数

Android深度探索(卷1)HAL与驱动开发 第六章 第一个Linux驱动程序:统计单词个数 统计单词个数的功能是封装在Linux驱动中的. Linux驱动的工作和访问方式是Linux亮点之一,同时受到了业界大防范好评.Linux系统将每一个驱动都映射成一个文件.这些文件称为设备文件或者驱动文件,都保存在 /dev 目录中.这种设计理念使得与Linux驱动进行交互就像与普通文件进行交互一样容易.当然,也比访问Linux API 更容易.由于大多数Linux驱动都有与其对应的设备文件,因此与Li

Android深度探索(卷1)HAL与驱动开发 第六章&#160;第一个Linux驱动程序:统计单词个数 读书笔记

本章是一个具体的例子,来详细的介绍开发和测试Linux驱动程序的完整过程.尤其是测试Linux驱动.在这个统计单词个数的实例中,重点是该算法的实现技术:即Linux驱动,而不是如何统计的. 6.1Linux驱到底是什么 Linux驱动的工作方式和访问方式是Linux的特点之一.Linux系统将每一个驱动都映射成一个文件,这些文件被称为驱动文件或设备文件,保存在dev目录中.由于大多数Linux驱动都有与其对应的设备文件,因此与Linux驱动交换数据就变成了与设备文件交换数据.事实上,编写Linu

把一个字符串里的所有单词的第一个字符转换为大写

//把一个字符串里的所有单词的第一个字符转换为大写  用到 了字符串方法split slice join charAt toUpperCase var str = 'ni hao ma!' function getUpper(str){ var words = str.split(' '); for(var i=0;i<words.length;i++){ words[i]=words[i].charAt(0).toUpperCase()+words[i].slice(1); } return