【发布时间】:2009-12-20 18:12:54
【问题描述】:
我搜索了一种方法来将打乱的单词与一个充满未打乱单词的单词列表进行比较,例如:
打乱的单词是“lonbayb”,单词表中的某个地方是单词“babylon”。脚本应该向我显示未加密的单词
知道如何解决这个问题吗?
【问题讨论】:
标签: php
我搜索了一种方法来将打乱的单词与一个充满未打乱单词的单词列表进行比较,例如:
打乱的单词是“lonbayb”,单词表中的某个地方是单词“babylon”。脚本应该向我显示未加密的单词
知道如何解决这个问题吗?
【问题讨论】:
标签: php
想到的一个简单解决方案是在比较之前按字母顺序对加扰和未加扰单词中的字母进行排序。我称之为“洗牌”:
"babylon" ==> "abblnoy"
实际上,您应该从参考词表中创建第二个词表,参考词表的条目会像这样随机排列。
然后当您查看一个新单词并想知道它是否在列表中时,以同样的方式随机播放,您可以在随机播放的参考列表中进行简单的搜索。如果您按字母顺序对打乱的参考列表中的单词进行排序,您甚至可以对其进行二分搜索。或者你将洗牌的参考词放入哈希集或 b-tree 中......任何容易快速搜索的东西。
【讨论】:
要随机播放单词,请使用str_shuffle()。
要将打乱的字符串与单词表进行比较,可以使用count_chars()。
class WordFinder
{
protected $_wordList;
protected $_map;
public function __construct(array $wordList)
{
$this->_wordList = $wordList;
}
protected function _initMap()
{
if(!is_array($this->_map)) {
$this->_map = array();
foreach($this->_wordList as $word) {
$key = count_chars($word, 3);
if(!isset($this->_map[$key])) {
$this->_map[$key] = array();
}
$this->_map[$key][] = $word;
}
}
}
public function findWords($searchWord)
{
$searchWord = count_chars($searchWord, 3);
$this->_initMap();
if(isset($this->_map[$searchWord])) {
return $this->_map[$searchWord];
}
return false;
}
}
那就做吧
$list = array('evil', 'live', 'vile', 'cat');
$finder = new WordFinder($list);
var_dump($finder->findWords('evli'));
这将返回
array(3) {
[0]=>
string(4) "evil"
[1]=>
string(4) "live"
[2]=>
string(4) "vile"
}
编辑 我已将原始代码与此版本进行了交换,因为它在处理大型单词列表时的性能要好得多。我已经在我的 2,2 Ghz 双核上测试了上述内容,它会在 0.08 秒内完成对 findWords() 的 10000 个单词集合中的 10000 次调用。另一个版本需要 207 秒。请参阅旧版本的修订。
【讨论】:
str_shuffle 是一个既定的PHP 函数,它做一些完全不同的事情,即改变字符的顺序随机。现在我正在考虑如何解决我可能无意中造成的任何混乱。
str_shuffle 来打乱单词,因为count_chars 无论如何都会按字母顺序返回它们。不需要 1:1 的地图。