如何为anagram应用程序(php)创建子集单词?

时间:2009-07-02 13:12:40

标签: php string anagram

我创建了一个anagram创建应用程序,通过在我的数据库中创建一个anagram字段,使用较低的按字母顺序存储的字符串。

例如,抽吸变为cinostu,耳朵变成空气,等等。

我现在要做的是从搜索到的原始字谜中创建子词。

示例:您如何从搜索“逮捕”中提取子集词,即“休息”和“凝视”。

6 个答案:

答案 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列。

使用字母计数导入整个字典后,您可以使用以下方法轻松确定给定单词中的所有可能子字词:

  • 计算字符串中的字母。
  • 撰写一个SQL查询,该查询返回您的字典表中的所有单词,这些单词不使用您给定单词中未找到的字母,或者您的单词中存在的字母数量多于此字母。

你可以通过制作一个包含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)

嘿博克。一直在努力使你的代码适应PHP,我有以下内容:

$ 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]]++;
}