如何使用变量和标记实现马尔可夫算法?

时间:2015-10-04 23:17:26

标签: java recursion replace cycle markov

我一直在努力实现马尔可夫的算法,但我只取得了部分成功。该算法非常简单,可以找到here

但是,我的项目有一个额外的难度,我必须使用包含标记和变量的规则。

变量表示字母表中的任何字母,而标记只是一个字符,用作移动变量的参考(它没有实际值)。

此示例复制字符串中的每个字符:

  

字母:{a,b,c}

     

标记:{M}

     

变量:{x}

     

规则1:Mx - > xxM

     

规则2:xM - > X

     

规则3:x - > MX

     

输入:abc

     

abc //我们应用规则3

     

Mabc //我们应用规则1

     

aaMbc //我们应用规则1

     

aabbMc //我们应用规则1

     

aabbccM //我们应用规则2

     

为aabbcc

这是我的递归函数,它实现了一个仅适用于字符串输入的马尔可夫算法,例如:规则1:“apple” - > “橙色”,输入:“apple”。

public static String markov(String input, LinkedList<Rule> rules) {
    for (Rule rule : rules) {
        if (!input.equals(input.replace(rule.getFrom(), rule.getTo()))) { //If the rule matches a substring
            if (rule.isTerminating()) { //If the rule is terminating
                input = input.replaceFirst(Pattern.quote(rule.getFrom()), rule.getTo());
                System.out.println(input); //Replace the first instance
                return input; //return and end the cycle
            } else {
                input = input.replaceFirst(Pattern.quote(rule.getFrom()), rule.getTo());
                System.out.println(input);
                return markov(input, rules); //Start looking again for matching rules
            }
        }
    }
    return input;
}

我无法弄清楚如何在这个逻辑中实现变量和标记,所以也许有人可以教会我实现这个逻辑的最佳方法?欢迎任何建议。

如果问题不符合SO指南,请在评论中告诉我,为什么我不重复这个错误。

谢谢!

GitHub

1 个答案:

答案 0 :(得分:0)

我认为最简单的方法是使用Java正则表达式。一旦你了解了这些,那么以下规则应该适用于你的例子:

Rule 1: "M([a-c])" -> "$1$1M"
Rule 2: "([a-c])M" -> "$1" (terminating)
Rule 3: "([a-c])"  -> "M$1"

请注意,您需要对当前方法进行一些调整才能使其正常工作......

replace采用文字字符串作为第一个参数,而replaceFirst使用正则表达式,所以:

replace: if (!input.equals(input.replace(rule.getFrom(), rule.getTo()))) {
with:    if (!input.equals(input.replaceFirst(rule.getFrom(), rule.getTo()))) {

您引用的rule.getFrom()字符串不适用于正则表达式,因此:

replace: input = input.replaceFirst(Pattern.quote(rule.getFrom()), rule.getTo());
with:    input = input.replaceFirst(rule.getFrom(), rule.getTo());

此时,您在调用replaceFirst两次的代码中有一些重复,因此您可以在第一次将其粘贴到临时变量中并重复使用它:

String next = input.replace(rule.getFrom(), rule.getTo());
if (!input.equals(next)) {
  ...
  input = next;
  ...
}

当你正在引用整个rule.getFrom()字符串时,我猜你之前遇到过正则表达式特殊字符的问题。如果是这样,您将需要在创建规则时单独解决它们。我真的不想进入正则表达式,因为它是一个巨大的区域,并且完全独立于马尔可夫算法,所以如果您遇到这些问题,请在线进行一些研究(例如Regular Expressions和{ {3}}),或在这里提出一个单独的问题,重点关注正则表达式特定问题。

请注意,您仍然可以将这些与常规规则结合使用(将标记字符从M更改为#以允许M在字母表中使用),这些规则:

"A"             -> "apple"
"B"             -> "bag"
"S"             -> "shop"
"T"             -> "the"
"the shop"      -> "my brother"
"#([a-zA-Z .])" -> "$1$1#"
"([a-zA-Z .])#" -> "$1" (terminating)
"([a-zA-Z .])"  -> "#$1"

会转换:

from: I bought a B of As from T S.
to:   II  bboouugghhtt  aa  bbaagg  ooff  aapppplleess  ffrroomm  mmyy  bbrrootthheerr..

希望这有帮助。