【问题标题】:Dynamic programming-memoization动态编程记忆
【发布时间】:2012-06-02 07:10:19
【问题描述】:

我正在处理一个 DP 问题,其中删除了空格的字符串,我需要实现自下而上和记忆化版本以将字符串拆分为单个英文单词。然而,我得到了自下而上的版本,然而,记忆似乎有点复杂。

 /* Split a string into individual english words
 * @String str the str to be splitted
 * @Return a sequence of words separated by space if successful,
     null otherwise
 */
public static String buttom_up_split(String str){
    int len = str.length();
    int[] S = new int[len+1];
    /*Stores all the valid strings*/
    String[] result = new String[len+1];  
    /*Initialize the array*/
    for(int i=0; i <= len; i++){
        S[i] = -1;
    }
    S[0] =0;
    for(int i=0; i < len; i++){
        if(S[i] != -1){
            for(int j= i+1; j <= len; j++){
                String sub = str.substring(i, j);
                int k = j;      
                if(isValidEnglishWord(sub)){
                    S[k] = 1; //set true indicates a valid split
                    /*Add space between words*/
                    if(result[i] != null){ 
                        /*Add the substring to the existing words*/
                        result[i+ sub.length()] = result[i] + " " + sub;
                    }
                    else{
                        /*The first word*/
                        result[i+ sub.length()] = sub;
                    }
                }

            }
        }
    }
    return result[len];  //return the last element of the array
}

我真的很困惑如何将这个buttom_up_version转换为memoized版本,希望有人能帮助..

【问题讨论】:

    标签: java dynamic memoization


    【解决方案1】:

    好吧,我不是记忆的出口,但我的想法是对以前的好英语单词有一个“记忆”。 目标是节省计算时间:在您的情况下,调用 isValidEnglishWord()。

    因此,您需要以这种方式调整您的算法:

    1. 遍历“str”字符串
    2. 从中提取一个子字符串
    3. 检查子字符串是否是您记忆中的有效单词。
      1. 它在内存中:在结果中添加一个空格和单词。
      2. 它不在内存中:调用 isValidEnglishWord 并处理它的返回。

    它会给出类似的东西(未经测试或编译)

    // This is our memory
    import java.util.*
    
    private static Map<String, Boolean> memory = new HashMap<String, Boolean>()
    
    public static String buttom_up_split(String str){
       int len = str.length();
       int[] S = new int[len+1];
    
       String[] result = new String[len+1];  
       for(int i=0; i <= len; i++){
          S[i] = -1;
       }
       S[0] =0;
       for(int i=0; i < len; i++){
          if(S[i] != -1){
             for(int j= i+1; j <= len; j++){
                String sub = str.substring(i, j);
                int k = j;    
    
                // Order is significant: first look into memory !
                Boolean isInMemory = memory.contains(sub);
                if (isInMemory || isValidEnglishWord(sub)){
                    S[k] = 1;
                    if(result[i] != null){ 
    
                        // Memoize the result if needed.
                        if (!isInMemory) {
                            memory.put(sub, true);
                        }
    
                        result[i+ sub.length()] = result[i] + " " + sub;
                    } else {
                        result[i+ sub.length()] = sub;
                    }
                }
    
            }
        }
    }
    return result[len];
    

    }

    【讨论】:

      【解决方案2】:

      就我个人而言,我总是更喜欢在不修改算法的情况下尽可能透明地使用记忆。这是因为我希望能够与记忆分开测试算法。此外,我正在开发一个 memoization 库,您只需将 @Memoize 添加到 memoization 适用的方法中。但不幸的是,这对你来说太迟了。

      上次我使用 memoization(没有我的库)时,我使用 proxy class 实现了它。一个重要的说明是这个实现不支持递归。但这应该不是问题,因为您的算法不是递归的。

      其他一些参考是:

      关于您的算法的评论: 您如何处理包含其他单词的单词?比如“verbose”包含“verb”,“theory”包含“the”等等……

      【讨论】:

        猜你喜欢
        • 2013-05-11
        • 1970-01-01
        • 2021-10-01
        • 1970-01-01
        • 2020-12-10
        • 2010-10-15
        • 2023-03-05
        • 2011-09-05
        相关资源
        最近更新 更多