题目:
CC150上面的17章最后一题,将一个去掉标点空格大写字母变小写的字符串,根据给定的字典,算出解析后的句子。
Code:
class Test{
public static void main(String[] args){
Test test = new Test();
Trie<Integer> dic = new Trie<Integer>();
dic.put("i", 1);
dic.put("love", 2);
dic.put("you", 3);
dic.put("cinderella", 4);
String str = "iloveyoucinderella";
HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>(); //<WordStart, Minimum...>
test.parseString(str, hm, dic, 0, 0);
for(Integer key : hm.keySet()){
System.out.println(key + " : " + hm.get(key));
}
}
public int parseString(String str, HashMap<Integer, Integer> hm, Trie<Integer> dic, int start, int end){
if(end >= str.length()) return end - start;
if(hm.containsKey(start)) return hm.get(start);
String cur = str.substring(start, end+1);
int bestExact = parseString(str, hm, dic, start+1, end+1), bestExtend = Integer.MAX_VALUE;
if(!dic.containPart(cur)) bestExact += cur.length();
else bestExtend = parseString(str, hm, dic, start, end+1);
int res = Math.min(bestExact, bestExtend);
hm.put(start, res);
return res;
}
}
class Trie<Value>{
public static int acs = 256;
Node root = new Node();
private static class Node{
Object value;
Node[] next = new Node[acs];
}
//递归插入
public void put(String key, Value value){
put(root, key, value, 0);
}
private Node put(Node x, String key, Value value, int pos){
if(x==null) x = new Node();
if(pos == key.length()){
x.value = value;
return x;
}
char c = key.charAt(pos);
x.next[c] = put(x.next[c], key, value, pos+1);
return x;
}
//递归搜索
public Value get(String key){
return get(root, key, 0);
}
private Value get(Node x, String key, int pos){
if(x == null) return null;
if(pos == key.length()) return (Value)x.value;
char c = key.charAt(pos);
return get(x.next[c], key, pos+1);
}
/*
//非递归插入
public void put(String key, Value value){
int i = 0;
Node cur = root;
while(i < key.length()){
char c = key.charAt(i);
if(cur.next[c] == null){
Node x = new Node();
cur.next[c] = x;
}
cur = cur.next[c];
i++;
}
if(i == key.length()) cur.value = value;
}
//非递归搜索
public Value get(String key){
int i = 0;
Node cur = root;
while(i < key.length()){
char c = key.charAt(i);
cur = cur.next[c];
if(cur == null) return null;
i++;
}
return (Value)cur.value;
}
*/
//contain part判断给定的key是否是trie结构中的一部分
public boolean containPart(String key){
Node cur = root;
int i = 0;
while(i < key.length()){
char c = key.charAt(i);
cur = cur.next[c];
if(cur == null) return false;
i++;
}
return true;
}
//contains方法
public boolean contains(String key){
return get(key)!=null;
}
}
总结:
解析方法是个递归,还没弄得很明白。另一个重点,这是第一次Trie的运用,以后还将有一道搜索引擎相关的应用。
补充:
经过两天的断断续续的思考,对着道题的递归解析有了进一步的认识,下面是改良版。
class Test{
public static void main(String[] args){
Test test = new Test();
Trie<Integer> dic = new Trie<Integer>();
// dic.put("i", 1);
dic.put("love", 2);
dic.put("you", 3);
// dic.put("cinderella", 4);
String str = "iloveyoucinderella";
HashMap<Integer, Result> hm = new HashMap<Integer, Result>(); //<WordStart, Minimum...>
System.out.println(test.parse(0, 0, hm, dic, str).parsed);
}
public Result parse(int start, int end, HashMap<Integer, Result> hm, Trie<Integer> dic, String str){
if(end >= str.length()){
return new Result(end-start, str.substring(start).toUpperCase());
}
if(hm.containsKey(start)) return hm.get(start).clone();
String cur = str.substring(start, end+1);
Result bestExact = parse(end+1, end+1, hm, dic, str);
if(!dic.contains(cur)){
bestExact.invalid += cur.length();
bestExact.parsed = cur.toUpperCase() + " " + bestExact.parsed;
}
else{
bestExact.parsed = cur + " " + bestExact.parsed;
}
Result bestExtend = null;
if(dic.containPart(cur)){
bestExtend = parse(start, end+1, hm, dic, str);
}
Result res = Result.min(bestExact, bestExtend);
hm.put(start, res.clone());
return res;
}
}
class Result{
int invalid = Integer.MAX_VALUE;
String parsed = "";
Result(int invalid, String parsed){
this.invalid = invalid;
this.parsed = parsed;
}
public Result clone(){
return new Result(this.invalid, this.parsed);
}
public static Result min(Result r1, Result r2){
if(r1 == null) return r2;
if(r2 == null) return r1;
return r1.invalid < r2.invalid ? r1 : r2;
}
}
class Trie<Value>{
public static int acs = 256;
Node root = new Node();
private static class Node{
Object value;
Node[] next = new Node[acs];
}
//递归插入
public void put(String key, Value value){
put(root, key, value, 0);
}
private Node put(Node x, String key, Value value, int pos){
if(x==null) x = new Node();
if(pos == key.length()){
x.value = value;
return x;
}
char c = key.charAt(pos);
x.next[c] = put(x.next[c], key, value, pos+1);
return x;
}
//递归搜索
public Value get(String key){
return get(root, key, 0);
}
private Value get(Node x, String key, int pos){
if(x == null) return null;
if(pos == key.length()) return (Value)x.value;
char c = key.charAt(pos);
return get(x.next[c], key, pos+1);
}
/*
//非递归插入
public void put(String key, Value value){
int i = 0;
Node cur = root;
while(i < key.length()){
char c = key.charAt(i);
if(cur.next[c] == null){
Node x = new Node();
cur.next[c] = x;
}
cur = cur.next[c];
i++;
}
if(i == key.length()) cur.value = value;
}
//非递归搜索
public Value get(String key){
int i = 0;
Node cur = root;
while(i < key.length()){
char c = key.charAt(i);
cur = cur.next[c];
if(cur == null) return null;
i++;
}
return (Value)cur.value;
}
*/
//contain part判断给定的key是否是trie结构中的一部分
public boolean containPart(String key){
Node cur = root;
int i = 0;
while(i < key.length()){
char c = key.charAt(i);
cur = cur.next[c];
if(cur == null) return false;
i++;
}
return true;
}
//contains方法
public boolean contains(String key){
return get(key)!=null;
}
}