3

我创建了一个字谜创建应用程序,通过在我的数据库中创建一个字谜字段,并使用小写字母顺序存储的字符串。

例如,吸力变为 cinostu,耳朵变为 aer,等等。

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

示例:您将如何从搜索“arrest”(即“rest”和“stare”)中提取子集词。

4

6 回答 6

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, art , aerst, aer, aer, aes, aet, aest, aers, aert, aerst, aerr, aers, aert, aerst, aerrs, aerrt, aerrst

3)然后根据您的排序列表检查这些字符串。出现在排序列表中的那些对应于您想要的子集词。

例如 aerrst 对应于完整的字谜(逮捕,稀有,光栅,...)
例如 aerst 将在您的排序列表中(凝视,眼泪,...)
例如 rrs 将不在您的排序列表中

于 2009-07-03T10:41:12.797 回答
1

在原始单词的末尾包含一个空格。空格在字母中间的每次迭代,你都会得到两个单词。然后你可以测试这两个词。如果空格位于迭代模式的开头或结尾,请将其剪掉并测试那个单词。

于 2009-07-02T13:22:28.953 回答
1

我还没有有意义地考虑这个问题,抱歉(工作要做!),但是无论你最终生成单词,不要忘记这会像妈妈一样缓存,所以不要去重新生成这些每次有人搜索时飞行。

CS。

于 2009-07-03T10:22:11.160 回答
0

这种方法与您的方法略有不同,但我相信它很容易以编程方式实现。我不确定它是否是最佳性能,但我会把它留给你:-)

首先,您需要一本包含您希望能够匹配的所有合法单词的字典。

在数据库中创建一个“字典”或“单词”表,第一列存储实际单词,第二列存储单词全部转换为大写或小写以便于比较,然后为每个字母一个整数列字母 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 个整数组成的数组(全部从 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 语句时,您将消除所有字母计数高于输入单词的单词 - 因此,如果原始单词中没有出现某个字母,您将过滤掉包含一个或多个该字母的单词。如果该字母出现一次,则过滤掉具有两个或更多该字母的单词,依此类推。

于 2009-07-02T13:46:04.303 回答
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 字母,因此错误地将数字添加到数组的末尾。

让我知道你认为我应该怎么做。

于 2009-07-03T10:02:50.597 回答
0

安迪,

我认为您需要将 ASCII 代码转换回字符 - 您正在用字母索引数组,但您正在使用 ASCII 值访问它。

这是您的代码,稍作修改:

$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 = **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]]++;
}
于 2009-07-03T10:41:22.063 回答