给定一本字典,找出最长的单词


Find the longest word given a dictionary

我多年来一直在阅读溢出,但从来没有发布过任何东西(感谢伟大的答案),直到现在,因为我不能真正找到我的问题的解决方案。我对PHP有点陌生。

所以我创造了一个游戏,你必须找到一个有12个随机生成的字母的最长单词。我实际上在c#和Java中成功地做到了这一点,但现在我正在将一些代码移植到PHP,因为我正在开发多人游戏版本,有些东西将在服务器上。

所以我做了这一切使用这个伟大的线程(回答由托马斯Jungblut):查找给定集合中最长的单词

现在我尝试在PHP中做同样的事情,但是,这对我来说很奇怪。我得到一些疯狂的结果,我不知道如何复制这个java方法在php:

 arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

我没有得到任何错误,但显然事情是不工作,有没有人可以帮助我解决这个问题?

更新:顺便说一句,我知道帖子可能会让我在这里发布的新手感到困惑…所以请原谅我^^我"修正"了代码,它现在会找到我最长的单词。但还是有问题。

允许算法多次使用一个字符,这是不可能的。

我认为问题在这里:

$newDict[$index] = array_splice($allowedCharacters, $index +1, count($allowedCharacters) - ($index +1));

我的当前代码:

parse_dictionary.php

<?php
$ouput = array();
$mysqli = new mysqli('localhost','root','','multiquiz_db');
$mysqli->set_charset('utf8'); 
if ($result = $mysqli->query("SELECT word FROM words_live")) {
    while($row = $result->fetch_array(MYSQL_ASSOC)) {
        //echo(mb_convert_encoding($row['word'], 'HTML-ENTITIES', 'utf-8'));
        array_push($ouput, $row['word']);
    }
    //echo utf8_decode(json_encode($ouput));
}
$result->close();
$mysqli->close();
?>

Trie.php

     <?php
class Trie
{
    public $children = array();
    public $value = null;
    public $word = null;
    public function __construct($value = null)
    {
        $this->value = $value;
    }
    public function adda($array)
    {
        $this->addb($array, 0);
    }
    public function addb($array, $offset)
    {
        foreach ($this->children as $child)
        {
            if($child->value == $array[$offset])
            {
                $child->addb($array, $offset + 1);
                return;
            }
        }
        $trieNode = new Trie($array[$offset]);
        array_push($this->children, $trieNode);
        if($offset < count($array) - 1)
        {
            $trieNode->addb($array, $offset+1);
        }
        else
        {
            $trieNode->word = implode(" ", $array);
        }
    }
}
?>

index . php

<?php
include 'Trie.php';
include 'parse_dictionary.php';
ini_set('memory_limit', '1024M'); // or you could use 1G
header('Content-Type: text/html; charset=utf-8');
mb_internal_encoding("UTF-8"); 
class LongestWord
{
    public $root = null;
    public function __construct($ouput)
    {
        $this->root = new Trie();
        foreach ($ouput as $word)
        {
            //echo($word);
            //echo(str_split_unicode($word)[0]);
            $this->root->adda(str_split_unicode($word));
        }
    }
public function search($cs)
{
    return $this->visit($this->root, $cs);
}
function visit($n, $allowedCharacters)
{
    $bestMatch = null;
    if(count($n->children) == 0)
    {
        $bestMatch = $n->word;
    }
    foreach($n->children as $child)
    {
        if($this->contains($allowedCharacters, $child->value))
        {
            $result = $this->visit($child, $this->remove($allowedCharacters, $child->value));
            if($bestMatch == null || $result != null && strlen($bestMatch) < strlen($result))
            {
                $bestMatch = $result;
            }
        }
    }
    return $bestMatch;
}
function remove($allowedCharacters, $value)
{
    $newDict = $allowedCharacters;
    if(($key = array_search($value, $newDict)))
    {
        unset($newDict[$key]);
    }
    return $newDict;
}
function contains($allowedCharacters, $value)
{
    foreach($allowedCharacters as $x)
    {
        if($value == $x)
        {
                //  echo $value . "=====". $x. "|||||||";
            return true;
        }
        else
        {
            //echo $value . "!!===". $x. "|||||||";
        }
    }
    return false;
}
}
function str_split_unicode($str, $l = 0) {
    if ($l > 0) {
        $ret = array();
        $len = mb_strlen($str, "UTF-8");
        for ($i = 0; $i < $len; $i += $l) {
            $ret[] = mb_substr($str, $i, $l, "UTF-8");
        }
        return $ret;
    }
    return preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);
}

$chars = 'IIOIOFNČGDĆJ';
$testCharacters = str_split_unicode($chars);
$lw = new LongestWord($ouput);
echo($lw->search($testCharacters));
?>

当您使用MySQL时,这里有一种方法可以让DB服务器完成工作。

有点脏,因为你必须添加几个WHERE条件与regex匹配,这将有相当差的性能。(不幸的是,我不能想出一个正则表达式,需要所有的字母在一个表达式中,但我很高兴被纠正。)

然而,我已经在一个>200000条目的数据库表上测试了它;它在不到0.3秒内提供结果。

SELECT word 
FROM words_live 
WHERE
    word REGEXP "a" AND 
    word REGEXP "b" AND 
    word REGEXP "c" AND 
    word REGEXP "d"
ORDER BY LENGTH(word) DESC 
LIMIT 1;

显然,在构造查询时,必须在PHP代码中为每个字母生成一个word REGEXP "a"条件。

查询应该只给出一个结果,即数据库中包含所有字符的最长单词。

我解决了这个函数的问题,完整的工作代码更新在问题后

function remove($allowedCharacters, $value)
{
    $newDict = $allowedCharacters;
    if(($key = array_search($value, $newDict)))
    {
        unset($newDict[$key]);
    }
    return $newDict;
}

删除旧的:

function remove($allowedCharacters, $value)
{
    $newDict = [count($allowedCharacters) - 1];
    $index = 0;
    foreach($allowedCharacters as $x)
    {
        if($x != $value)
        {
            $newDict[$index++] = $x;
        }
        else
        {
            //we removed the first hit, now copy the rest
            break;
        }
    }
    //System.arraycopy(allowedCharacters, index + 1, newDict, index, allowedCharacters.length - (index + 1)); JAVA  arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
    //$newDict[$index] = array_splice($allowedCharacters, $index +1, count($allowedCharacters) - ($index +1));
    //$newDict = $allowedCharacters;
    return $newDict;
}