2019阿里校招题--智能分词--Java解

本文深入探讨了智能分词算法的实现,通过构建Trie树和深度优先搜索(DFS)策略,有效地解决了字符串分词问题。文章详细介绍了如何将词汇表转化为Trie树,以及如何利用DFS遍历所有可能的分词组合,最终选取得分最高的分词方案。

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

今天又帮师兄们去做题了!这个题虽然不难但是还是比较费时间的。

一共两个题,到截止时间我才做出了第一题的一半,第二题都没看一眼,听其他人说第二题看都看不懂。。

把实现的java解和思路贴一下,只实现了功能,性能什么的没测试也没优化,感觉可能会超时。

 

题目:智能分词

分词是指将一个字符串分割成词语序列,其中所有词语都来自事先指定的词汇表。例如:

有字符串"github",以及词汇表["git","hub"],那么分词方式为:"git","hub"。

分词可能有多重方式,例如字符串"asdfjkl",以及词汇表["as","asd","df","fjkl","jkl"],可能有两种分词方法:"as df jkl"、"asd fjkl"。先定义每种分词方法的合理性得分为:分词方案中的每个单词长度的平方和。例如上述两种方案的得分分别为2^2+2^2+3^2=17,以及25分。

先给出词汇表(均小写,单词最长50,最多10w个),以及一句话(均小写,最长10w),找出最合理的方案。若有多种得分相同的最合理方案,输出长词尽量靠前的方案。如"ab cdef"和"abcd ef"输出"abcd ef"。

 

思路:

1、词汇表,弄成Trie

2、dfs处理字符串的分割以找齐所有情况

 

这里用了个数据结构来储存分割完的新String及其Score,全部完成后再取最合适的。

应该有更好的方法,在每次找出可能的字符串的时候直接与当前最佳进行比较,免去读取的时间消耗。

变量什么的也可以更好看,懒得改了。。

 

import java.util.LinkedList;

public class Hellowol {
	public static void main(String[] args) {
		Solution solution = new Solution();
		String[] words = {"git", "hub", "gi", "pp", "thu" ,"bpp"};
		String ans = solution.splitWord("githubpp", words);
		System.out.println(ans);
	}
}

class Solution {
	class TrieNode {
		TrieNode[] next = new TrieNode[26];
		String word;
	}
	class StrAndScore {
		String str;
		Integer score;
		StrAndScore(String str, Integer score) {
			this.str = str;
			this.score = score;
		}
	}
	
	private LinkedList<StrAndScore> list = new LinkedList<StrAndScore>();
	char temp[];
	TrieNode root;
	
	public String splitWord(String str, String[] words) {
		temp = str.toCharArray();
		
		/* build a trie*/
		root = new TrieNode();
		for(String w : words) {
			TrieNode p = root;
			for(char c : w.toCharArray()) {
				int i = c - 'a';
				if(p.next[i] == null) p.next[i] = new TrieNode();
				p = p.next[i];
			}
			p.word = w;
		}
		
		/*find all splited str and calculate score*/
		dfs(0, root.next[temp[0] - 'a'], "", 0);

		/*get the one with lowest score*/
		return getLowest(list);
	}

	private void dfs(int i, TrieNode p, String tempStr, int score) {
		if(i == temp.length-1) {
			list.add(new StrAndScore(tempStr + " "+ p.word, score + (p.word.length())*(p.word.length())));
			return;
		}
		if(p.word != null) {
			if(p.next[temp[i+1] - 'a'] != null) dfs(i+1, p.next[temp[i+1] - 'a'], tempStr, score);
			dfs(i+1, root.next[temp[i+1] - 'a'], tempStr + " " + p.word, score + (p.word.length())*(p.word.length()));
		}
		else if(p.word == null) {
			dfs(i+1, p.next[temp[i+1] - 'a'], tempStr, score);
		}
	}
	
	private String getLowest(LinkedList<StrAndScore> list) {
		String ans = "";
		int sc = Integer.MAX_VALUE;
		//can be better
//		for(StrAndScore sas : list) {
//			System.out.println("asdf   " + sas.str);
//		}
		for(StrAndScore sas : list) {
			if(sas.score < sc) {
				ans = sas.str;
				sc = sas.score;
			}
			if(sas.score == sc) {
				int i = 1;
				while(sas.str.charAt(i) != ' ') {
					if(ans.charAt(i) == ' ') {
						ans = sas.str;
						break;
					}
					i++;
				}
			}
		}

		return ans.substring(1);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值