2012-11-19 89 views
2

我使用马尔科夫模型创建伪随机文本生成器。基本上,我使用散列表来存储顺序k(马尔科夫模型的顺序)的子串的列表,然后对于每个子串,我有一个后缀的TreeMap以及它们在整个子串中的频率。Java - 采用字符频率,创建概率,然后生成伪随机字符

我正在努力生成随机后缀。对于每个子字符串,我有一个包含所有可能的后缀及其频率的TreeMap。我在使用它为每个后缀创建概率时遇到了麻烦,然后基于这些概率生成了伪随机后缀。

任何关于这个概念的帮助,以及如何去做这件事表示赞赏。如果您有任何问题或需要澄清,请告诉我。

+0

这个问题主要是数学问题吗? – durron597

+0

数学不是困难的部分。我知道如果一个后缀出现一次并且子字符串在文本中出现两次,那么它的概率是1/2,因此在文本生成器中出现1/2的时间。但是,手头的问题是如何获取这些信息,并从中产生一个“随机”字符。 – user1547050

回答

1

我不确定TreeMap是否真的是最好的数据结构,但是。 。 。

您可以使用the Math.random() method获取0.0(含)和1.0(不含)之间的随机值。然后,迭代你的地图元素,积累他们的频率,直到你超过这个值。首先超过此值的后缀是您的结果。假设你的地图元素的频率全部合计为1.0,这将选择与它们的频率成比例的所有后缀。

例如:

public class Demo 
{ 
    private final Map<String, Double> suffixFrequencies = 
     new TreeMap<String, Double>(); 

    private String getRandomSuffix() 
    { 
     final double value = Math.random(); 
     double accum = 0.0; 
     for(final Map.Entry<String, Double> e : suffixFrequencies.entrySet()) 
     { 
      accum += e.getValue(); 
      if(accum > value) 
       return e.getKey(); 
     } 
     throw new AssertionError(); // or something 
    } 

    public static void main(final String... args) 
    { 
     final Demo demo = new Demo(); 
     demo.suffixFrequencies.put("abc", 0.3); // value in [0.0, 0.3) 
     demo.suffixFrequencies.put("def", 0.2); // value in [0.3, 0.5) 
     demo.suffixFrequencies.put("ghi", 0.5); // value in [0.5, 1.0) 

     // Print "abc" approximately three times, "def" approximately twice, 
     // and "ghi" approximately five times: 
     for(int i = 0; i < 10; ++i) 
      System.out.println(demo.getRandomSuffix()); 
    } 
} 

注:

  • 由于舍入误差,则可能throw new AssertionError()实际上发生,每隔一段时间,尽管非常罕见。所以我建议你用一些总是选择第一个元素或最后一个元素或某物的东西来替换该行。
  • 如果频率不是全部合计为1.0,那么您应该在getRandomSuffix()的开头处添加一个合格的合格数来确定所有频率的总和。然后您可以相应地缩放value
+0

谢谢,我不知道entrySet()是什么,这使得这个过程变得简单很多。 – user1547050

+0

@ user1547050:不客气!我建议你阅读[java.util.TreeMap'的Javadoc](http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html);你可能会发现其他有用的东西。 (更普遍的是,我建议检查你打算使用的课程的Javadoc的习惯,通常会有惊喜,无论是好的还是坏的。) – ruakh