如何从字符数组中找到字符串匹配?恩。给定a,n,t find字符串匹配单词列表表中的ant,an,tan

时间:2012-10-28 15:36:38

标签: php mysql string string-matching

到目前为止,我的数据库中有27个表。一个单词表(拼字游戏单词列表)和26个关联表。

Table  Fields
================
word   [id,word]
a      [word_id,count]
b      [word_id,count]
...
z      [word_id,count]

我正在尝试找出给定字符串的匹配单词。

例如,如果给定的数组是a,n,t,我想知道:ant, tan, at, ta, an, na

我目前的策略是爆炸字符串中的每个字母,找到与所有字母匹配的相关字词。

例如:

SELECT word.word
FROM word, a, n, t
WHERE
    word.id = a.word_id OR
    word.id = n.word_id OR
    word.id = t.word_id

但最终会打印出所有包含a,n or t的字词。

如果我将所有操作符切换到AND,我只会遇到一个匹配:ant

你能帮我解决这个谜语吗?

我还关心如何处理字符串中的重复字母。我认为字母关联表中的count字段可以在这里提供帮助。如果单词为app,则p关联表中的计数将为2。

我是否在关联表的正确轨道上或者有更好的方法吗?

我正试图在php / mysql中相当有效地处理这个问题。我知道还有其他人在C,perl,java等之前解决了这个谜题。

1 个答案:

答案 0 :(得分:1)

如果你想要一个标准化的方法,那就是:

wordLetters{
  INT wordID,
  CHAR[1] letter,
  INT count,
  PK(wordID, letter)
}

words{
  INT wordID PK,
  VARCHAR(255) word UNIQUE
}

但这种方法在性能方面存在严重问题 - 即需要对字表进行全表扫描。我将假设没有太多的字母并建议这种方法:

words{
  INT wordID PK,
  VARCHAR(255) word UNIQUE,
  INT cA KEY,
  INT cB KEY,
  ...
  INT cZ KEY,
  KEY (cE, cT, cA, cO, cI, cN),
  ...
}

查询查询将很长但它会有效地使用索引,它仍然由PHP代码生成:

如果用户有[a,n,t],请将可用字词提取为:

SELECT word FROM words WHERE
   cA <= 1 AND cB = 0 AND cC = 0 AND ... AND cY = 0 AND cZ = 0

此查询将(可能)使用“ETAOIN”索引,因为不存在不需要“E”的单词。

此时,性能取决于仅可用于数据库的索引的选择,并且您始终可以添加更多索引(即使在运行时)。


关于数据库索引:

普通索引只是一个排序的项目列表,在列表上构建了适当的树,从而实现了有效的范围查找(从x到y获取所有元素)。

普通索引由其排序顺序定义。排序顺序是:首先按某些列排序,然后按另一列排序,然后按另一列排序......

例如,[E,T,A,O,I,N]索引将对所有单词进行排序:首先是所有不需要E的单词,然后是所有需要一个E的单词,然后是所有单词需要两个E ....需要相同数量的E s的单词将被排序:首先是所有不需要T的单词,然后是所有需要它的单词,然后是所有需要两个{{1}的单词s ....在需要相同数量的TE s的单词中,那些不需要T的单词首先出现。

如果要求数据库提取所有不需要AE且最多只有一个'X'的单词,则可以使用此索引来满足前两个要求,然后检查T范围内的所有单词。

特定的选择E=0, T=0基于短语ETAOIN SHRDLU,它按照频率命令英语中十二个最常用的字母 - 这意味着如果使用此索引,则应过滤掉尽可能多的单词。

您使用示例ETAOIN。当玩家没有RSTLNER时,将会/可能会使用此索引。对查找进行基准测试可以告诉您使用每个特定索引节省了多少时间。

您可以使用EXPLAIN EXTENDED查询来查看哪些索引被考虑并随后用于每个特定查询以及预计要过滤掉多少行。例:

S