我创建了一个anagram创建应用程序,通过在我的数据库中创建一个anagram字段,使用较低的按字母顺序存储的字符串。
例如,抽吸变为cinostu,耳朵变成空气,等等。
我现在要做的是从搜索到的原始字谜中创建子词。
示例:您如何从搜索“逮捕”中提取子集词,即“休息”和“凝视”。
答案 0 :(得分:2)
这是我之前使用的一种方法,它使用了按字母顺序排序的单词列表。
1)拿出你的目标词(逮捕)并对其进行分类(aerrst)。
2)然后从排序的单词生成新的字符串,其中包含或排除每个字母。对于N个字母的单词,这给出了2 ** N个可能的字符串。 (我不知道PHP,但如果你愿意,可以给你伪代码或Python。)
对于您的目标词,我们有: a,e,r,r,s,t,st,rs,rt,rst,rr,rs,rt,rst,rrs,rrt,rrst,er,er,es,et,est,ers,ert,erst, err,ers,ert,erst,errs,errt,errst,ae,ar,ar,as,at,ast,ars,art,arst,arr,ars,art,arst,arrs,arrt,arrst,aer,aer, aes,aet,aest,aers,aert,aerst,aerr,aers,aert,aerst,aerrs,aerrt,aerrst
3)然后根据您的排序列表检查这些字符串。出现在排序列表中的那些对应于您想要的子集单词。
例如,aerrst对应于完整的字谜(逮捕,最稀有,光栅......)
例如aerst将在你的排序列表中(凝视,眼泪,......)
例如,rrs不在您的排序列表中
答案 1 :(得分:1)
在原始单词的末尾添加空格。空间最终在字母中间的每次迭代,你会得到两个单词。然后你可以测试这两个词。如果空间位于迭代模式的开头或结尾,请将其修剪掉并测试一个单词。
答案 2 :(得分:1)
我还没有想到这个有意义的,抱歉(要做的工作!),但是你最终会产生这些词,不要忘记这会像母亲一样缓存,所以不要重新生成每当有人搜索时,这些就会出现。
CS。
答案 3 :(得分:0)
这种方法与您的方法略有不同,但我相信以编程方式实现起来很容易。我不确定这是最佳表现,但我会把它留给你: - )
首先,您需要一个您希望能够匹配的所有合法字词的字典。
在数据库中创建一个“Dictionary”或“Words”表,第一列存储实际的单词,第二列存储将单词转换为大写或小写以便于比较,然后为每个单词存储一个整数列字母AZ中的字母。
将您的字典文件导入此表格,并以编程方式计算该字母中每个字母出现的次数,并将该数字存储在该字母的列中。
示例Word:簿记员
将单词“bookkeeper”存储在单词列中,将“b”,“p”和“r”列中的1,“o”和“k”列中的2,以及“e”中的3列。
使用字母计数导入整个字典后,您可以使用以下方法轻松确定给定单词中的所有可能子字词:
你可以通过制作一个包含26个代表字母的位置的内存数组来实现这一点
示例词:车辆
SELECT Word FROM Dictionary WHERE NOT (
(a >= 1) OR (b >= 1) OR (c >= 2) ... OR (z >= 1)
)
因此,排除了字典中包含“a”或“z”的任何单词,因为查询将过滤掉“a”或“z”计数至少为1的任何单词,并且任何使用多个'c'的单词都会被过滤掉。
您可以通过使用26个整数的数组以编程方式轻松生成所有“OR”条件,所有这些都从1开始,然后查看您的单词,将1添加到您找到的每个字母的相应数组值。
更新 - 最终计数示例代码
请原谅我下面的代码示例 - 它将在ASP(VBScript)中 - 但您应该能够掌握并翻译成PHP,或者如果没有,那么请一位善良的人为您执行此操作。
Const AsciiCodeLowerCaseA = 97
InputWord = "Carrots"
LowerCaseInputWord = LCase(InputWord)
Dim LetterCount(26)
for i = 1 to 26
LetterCount(i) = 1
next
for j = 1 to Len(InputWord)
CurrentLetter = Mid(InputWord, j, 1)
AsciiCode = Chr(CurrentLetter)
AlphabetPos = AsciiCode - AsciiCodeLowerCaseA + 1
LetterCount(AlphabetPos) = LetterCount(AlphabetPos) + 1
next
通过将单词的每个字母转换为其ASCII值,然后减去小写'a'的ascii代码并添加1,您将从1到26的字母表中获得该字母的位置。现在将1添加到数组中的那个位置。
这似乎违反直觉,但是在数组中将所有字母初始化为1。在构建SQL语句时,您将删除字母数高于输入字的所有单词 - 因此,如果原始单词中没有出现字母,则过滤掉具有该字母中一个或多个字母的单词。如果该字母出现一次,则过滤掉具有该字母中两个或更多字母的单词,依此类推。
答案 4 :(得分:0)
$ LetterCount = array(“a”=> 1,“b”=> 1,“c”=> 1,“d”=> 1,“e”=> 0,“f “=> 1,”g“=> 1,”h“=> 1,”i“=> 1,”j“=> 1,”k“=> 1,”l“= > 1,“m”=> 1,“n”=> 1,“o”=> 1,“p”=> 1,“q”=> 1,“r”=> 1,“s”=> 1,“t”=> 1,“u”=> 1,“v”=> 1,“w”=> 1,“x”=> 1, “y”=> 1,“z”=> 1);
$AsciiCodeLowerCaseA = 97;
for ($j = 1; $j < strlen($string); $j++) {
$CurrentLetter = $string[$j];
$AsciiCode = ord($CurrentLetter);
$AlphabetPos = $AsciiCode - $AsciiCodeLowerCaseA + 1;
$LetterCount[$AlphabetPos] = $LetterCount[$AlphabetPos] + 1;
}
我硬编码了数组声明位以节省时间。
无论如何,它似乎没有工作,并给了我这个错误:注意:未定义的偏移量:1
这是我得到的错误的屏幕截图,我还为循环中的每个var或数组添加了回声,看看你是否能理解发生了什么。
http://i42.tinypic.com/11ryz4g.png
我认为它无法正确识别数组中的aplhabet字母,因此会错误地将数字添加到数组的末尾。
让我知道你认为我应该做些什么。
答案 5 :(得分:0)
安迪,
我认为您需要将ASCII代码转换回字符 - 您使用字母索引数组,但是您使用ASCII值访问它。
这是您的代码,略有修改:
$ LetterCount = array(“a”=&gt; 1,“b”=&gt; 1,“c”=&gt; 1,“d”=&gt; 1,“e”=&gt; 0,“f “=&gt; 1,”g“=&gt; 1,”h“=&gt; 1,”i“=&gt; 1,”j“=&gt; 1,”k“=&gt; 1,”l“= &gt; 1,“m”=&gt; 1,“n”=&gt; 1,“o”=&gt; 1,“p”=&gt; 1,“q”=&gt; 1,“r”=&gt; 1,“s”=&gt; 1,“t”=&gt; 1,“u”=&gt; 1,“v”=&gt; 1,“w”=&gt; 1,“x”=&gt; 1, “y”=&gt; 1,“z”=&gt; 1);
$AsciiCodeLowerCaseA = 97;
for ($j = **0**; $j < strlen($string); $j++) {
$CurrentLetter = $string[$j];
$AsciiCode = ord($CurrentLetter);
$AlphabetPos = **chr($AsciiCode - $AsciiCodeLowerCaseA + 1);**
$LetterCount[$AlphabetPos] = $LetterCount[$AlphabetPos] + 1;
}
另外我只是注意到你要从1开始索引字符串中的字符,但是数组是零识别的。
我认为这也可能更简单(除非我遗漏了什么)
for($j = 0; $j < strlen($string); $j++) {
$LetterCount[$string[$j]]++;
}