为了实现DP算法,用于检测单词是否可以分解为长度为n' n的子字。为什么应该选择用于缓存DP结果的数据结构。 示例: “' pita'可以分解成“坑”,“它”和“#”; &安培; '我'这些都是有效的字典单词。 DP算法应该检测这样的单词。
我可以想象我需要从长度为1的单词开始并构建不断增加长度的子串,但是我无法获得能够有效存储子问题结果的数据结构
答案 0 :(得分:1)
如果您处理单词顺序,则不需要跟踪之前的单词,因为您无法再次访问它们,但您可以使用缓存来缓存字典中先前查找的子单词。 如果我理解了这个问题,那么我认为以下Java代码可以帮助您:
String term = "pita";
Set<String> dictionary = new HashSet<String>();
boolean ans = true;
for(int i = 0; i < term.length() && ans == true; i++) {
for(int j = i + 1; j < term.length(); j++) {
String subTerm = term.substring(i, j);
if(!dictionary.contains(subTerm)){
ans = false;
break;
}
}
}
System.out.println("ans [" = ans + "]");
对于字典,您可以使用哈希表,它支持使用O(1)来检查子字节 字存在与否。如果你缓存先前检查过的子词,它将采用相同的O(1)
我认为这个问题适用于不在DP中的排序和搜索技术,因为 它没有使用先前的答案来产生当前答案。
答案 1 :(得分:1)
不需要特殊的数据结构,因为这样的布尔DP阵列就足够了: -
isSentence [j]告诉子串str [j到n]是有效串联的 英语单词/ word其中n是最后一个索引
对于所有我来说,isSentence [j] =或(isword(str [j to i])&amp;&amp; isSentece [i + 1]) 从j到n
或者这里表示所有子问题的逻辑OR,isword是字典 查找返回布尔值和&amp;&amp;逻辑AND
答案 2 :(得分:0)
我可以想象我需要从长度为1的单词开始并构建不断增加长度的子串,但是我无法获得能够有效存储子问题结果的数据结构
以下是用 Java 编写的伪代码可能无法编译
<强> TrieNode.java 强>
class TrieNode
{
public TrieNode (double a, double b, double g, int size)
{
this.alpha = a;
this.beta = b;
this.gamma = g;
this.next = new TrieNode [size];
}
public double alpha, beta, gamma;
public TrieNode [] next;
}
您可以将alpha
,beta
,gamma
替换为问题参数。
<强> Trie.java 强>
class Trie
{
private TrieNode root;
private char base;
private final int ALPHABET_SIZE;
public Trie (int ALPHABET_SIZE, char base_char)
{
this.base = base_char;
this.root=new TrieNode(0,0,0,ALPHABET_SIZE);
}
public boolean insert (String word, double [] param)
{
TrieNode current = this.root;
int i = (-1);
if (!validate(word))
return false;
char [] c = word.toCharArray();
for (int i = 0; i < (c.length-1); i++)
{
if (current.next[c[i]-base] == null)
current.next[c[i]-base] = new TrieNode (0,0,0,ALPHABET_SIZE);
current = current.next[c[i]-base];
}
if (current.next[c[i]-base] == null)
current.next[c[i]-base] = new TrieNode (0,0,0,ALPHABET_SIZE);
current.next[c[i]-base].alpha = param[0];
current.next[c[i]-base].beta = param[1];
current.next[c[i]-base].gamma = param[2];
return true;
}
public boolean validate (String word)
{
for (char c : word.toCharArray())
if (c < base || c > (base+ALPHABET_SIZE-1))
return false;
}
}
这是一个基于索引的Trie,具有安全插入功能。
<强> MappedTrie.java 强>
class MappedTrie
{
public final char [] ALPHABET;
private Trie trie;
MappedTrie (char [] alphabet)
{
ALPHABET = alphabet;
trie = new Trie (ALPHABET.length,0);
}
public boolean insert (String word, double [] param)
{
if (!validate(word))
return false;
String key = "";
for (char c : word.toCharArray())
key += encode(c);
return trie.insert(key,param);
}
private char encode (char c)
{
for (int i=0; i<ALPHABET.length; i++)
if (c == ALPHABET[i])
return i;
}
private char decode (char d)
{
return ALPHABET[d];
}
public boolean validate (String word)
{
boolean exist = false;
for (char c : word.toCharArray())
{
exist = false;
for (char d : ALPHABET) if (c == d) { exist = true; break; }
if (!exist) return false;
}
return true;
}
}
如果字符不是adjecent的自定义字母,我们可以将其映射到索引。
<强>测试强>
class Test
{
public static void main (String [] args)
{
// 'a'+0, 'a'+1, 'a'+2
MappedTrie k = new MappedTrie(3, 'a');
k.insert("aa", { 0.1, 0.2, 0.3 });
k.insert("ab", { 0.4, 0.5, 0.6 });
k.insert("ac", { 0.7, 0.8, 0.9 });
k.insert("ba", { 0.01, 0.02, 0.03 });
k.insert("bb", { 0.04, 0.05, 0.06 });
k.insert("bc", { 0.07, 0.08, 0.09 });
k.insert("ca", { 0.001, 0.002, 0.003 });
k.insert("cb", { 0.004, 0.005, 0.006 });
k.insert("cc", { 0.007, 0.008, 0.009 });
// 'a' => 0, 'b' => 1, 'c' => 2
MappedTrie t = new MappedTrie({'a','b','c'});
t.insert("aa", { 0.1, 0.2, 0.3 });
t.insert("ab", { 0.4, 0.5, 0.6 });
t.insert("ac", { 0.7, 0.8, 0.9 });
t.insert("ba", { 0.01, 0.02, 0.03 });
t.insert("bb", { 0.04, 0.05, 0.06 });
t.insert("bc", { 0.07, 0.08, 0.09 });
t.insert("ca", { 0.001, 0.002, 0.003 });
t.insert("cb", { 0.004, 0.005, 0.006 });
t.insert("cc", { 0.007, 0.008, 0.009 });
}
}
答案 3 :(得分:0)
我认为使用unordered_map<string, int>
或unordered_set<string>
可能会非常有帮助。