【问题标题】:PHP: Finding word in graph of letters recursivelyPHP:递归地在字母图中查找单词
【发布时间】:2017-05-14 16:07:11
【问题描述】:

我有这样的图表:

现在,假设我正在寻找一个词 CAT。我正在尝试编写一个很好的代码来遍历这个图表并找到一个单词。我希望它能找到一个单词的所有现有位置,而不仅仅是第一个。

$graph->find('cat') 的结果应该是:

return [
    [1, 0, 6],
    [1, 2, 3]
];

我过去创建过这样的代码,但它是迭代的。这次我想试试递归。

这是我目前所拥有的:

我这样称呼它:

// LetterGraph is my own class
$graph = new LetterGraph($nodes);
$graph->find('cat');

在我的 LetterGraph 课程中,我执行以下操作:

public function find(string $word): array {
    $result = [];

    $firstLetter = mb_substr($word, 0, 1);

    foreach ($this->letters as $node) {
        if ($node->letter === $firstLetter) {
            $result[] = $this->walk($word, [$node]);
        }
    }

    return $result;
}

protected function walk(string $word, array $nodes): array {
    $lastNode = end($nodes);

    $letterToFind = mb_substr($word, count($nodes), 1);

    foreach ($lastNode->neighbours as $neighbour) {
        if ($neighbour->letter === $letterToFind) {
            // is return okay here?
            return $this->walk($word, array_merge($nodes, $neighbour);
        }
    }
}

现在,我不确定如何处理递归返回以使其得到我想要的结果。

【问题讨论】:

  • 如何定义图中的边? new LetterGraph(['a', 'c', 'a', 't', 'b', 'r', 't']); 仅定义节点。
  • 是的,我简化了一点。让我们假设每个$node 都可以访问$node->neighbours

标签: php algorithm recursion graph


【解决方案1】:

可以使用Master theorem 解决。 假设 $node->id 是您希望在结果数组中看到的数字,递归可能看起来像

public function find(string $word, array $nodes = null): array
{

    $firstLetter = mb_substr($word, 0, 1);
    $rest = mb_substr($word, 1);

    if (empty($nodes)) {
        //top level call, start to search across all nodes
        $nodes = $this->letters;
    }

    $result = [];

    foreach ($nodes as $node) {
        if ($node->letter === $firstLetter) {
            if (empty($rest)) {
                //exit recursion
                $result[] = [$node->id];
            } else {
                //recursively search rest of the string
                $branches = $this->find($rest, $node->neighbours);
                if (!empty($branches)) {
                    foreach ($branches as $branch) {
                        $result[] = array_merge([$node->id], $branch);
                    }
                }
            }
        }
    }
    return $result;
}

【讨论】:

  • 我尝试使用您的策略将结果添加到数组中,但我无法使其工作。这是我现在的 find() 方法:gist.github.com/anonymous/9c8ba7f55ffcc629a68be91b3ef84ff4
  • @RoboRobok,您的要点与我发布的内容并不接近。我相信我的伪代码是不言自明的,它显示了如何遍历图形以及它存在迭代的位置。如果您在调试 您的 代码方面需要任何帮助,您必须提供可重现的 mcve。理想情况下,通过失败的测试来暴露您的期望。
  • 我不太明白为什么你的代码把节点ID放在最前面,为什么你把单个节点ID放在结果集中,剩下的都是空的。
  • 好吧,当$word 是一个字母时,$rest 是空的,不是吗?所以它是单词中的最后一个字符。当我们找到所有最后的节点时,我们将它们的 id 添加到结果中,并退出递归。
  • 我检查了你的代码并且它有效:) 不过我需要理解它。我有一种感觉,它可以进一步简化。
猜你喜欢
  • 2019-08-26
  • 1970-01-01
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2021-08-26
相关资源
最近更新 更多