动态编程的数据结构选择

时间:2014-06-18 04:16:31

标签: algorithm data-structures dynamic-programming

为了实现DP算法,用于检测单词是否可以分解为长度为n' n的子字。为什么应该选择用于缓存DP结果的数据结构。 示例: “' pita'可以分解成“坑”,“它”和“#”; &安培; '我'这些都是有效的字典单词。 DP算法应该检测这样的单词。

我可以想象我需要从长度为1的单词开始并构建不断增加长度的子串,但是我无法获得能够有效存储子问题结果的数据结构

4 个答案:

答案 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;
}

您可以将alphabetagamma替换为问题参数。

<强> 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>可能会非常有帮助。