今天又帮师兄们去做题了!这个题虽然不难但是还是比较费时间的。
一共两个题,到截止时间我才做出了第一题的一半,第二题都没看一眼,听其他人说第二题看都看不懂。。
把实现的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);
}
}