6

我有一个包含字典中单词的数据库表。

现在我想为字谜选择单词。例如,如果我给出字符串SEPIAN,它应该获取诸如apes, pain, pains, pies, pines, sepia, 等的值。

为此,我使用了查询

SELECT * FROM words WHERE word REGEXP '^[SEPIAN]{1,6}$'

但是此查询返回的单词如annaessen其重复字符不在提供的字符串中。例如。anna有两个,但搜索字符串n中只有一个。nSEPIAN

我怎样才能编写我的正则表达式来实现这一点?此外,如果当时我的搜索字符串中有重复字符,则重复字符应反映在结果中。

4

2 回答 2

5

由于 MySQL 不支持反向引用捕获组,典型的解决方案是(\w).*\1行不通的。这意味着给出的任何解决方案都需要枚举所有可能的双精度数。此外,据我所知,反向引用在前瞻或后视中无效,并且 MySQL 不支持前瞻和后视。

但是,您可以将其拆分为两个表达式,并使用以下查询:

SELECT * FROM words
WHERE word REGEXP '^[SEPIAN]{1,6}$'
AND NOT word REGEXP 'S.*?S|E.*?E|P.*?P|I.*?I|A.*?A|N.*?N'

不是很漂亮,但它可以工作,而且应该也相当有效。


要支持一组重复字符的限制,请为您的辅助表达式使用以下模式:

A(.*?A){X,}

A你的角色在哪里,X是允许的次数。

因此,如果您在N字符串中添加另一个SEPIANN(总共 2N秒),您的查询将变为:

SELECT * FROM words
WHERE word REGEXP '^[SEPIAN]{1,7}$'
AND NOT word REGEXP 'S.*?S|E.*?E|P.*?P|I.*?I|A.*?A|N(.*?N){2}'
于 2012-07-16T13:20:25.847 回答
2

我想这样的事情会帮助你。表words

| id    | word      | alfagram  |
---------------------------------
| 1     | karabar   | aaabkrr   |
| 2     | malabar   | aaablmr   |
| 3     | trantantan| aaannnrttt|

alfagram这是按字母顺序排列的单词的字母。

PHP代码:

$searchString = 'abrakadabra';
$searchStringAlfa = array();
for( $i=0,$c=strlen($searchString);$i<$c;$i++ ){
    if( isset($searchStringAlfa[$searchString[$i]]) ){
        $searchStringAlfa[$searchString[$i]]++;
    }else{
        $searchStringAlfa[$searchString[$i]] = 1;
    }
}
ksort($searchStringAlfa);
$regexp = '^';
foreach( $searchStringAlfa as $alfa=>$amount ){
    $regexp .= '['.$alfa.']{0,'.$amount.'}';
}
$regexp .= '$';

$searchString是您要搜索的字符串。那么你唯一应该做的就是执行查询:

$result = mysql_query('SELECT * FROM words WHERE alfagram REGEXP "'.$regexp.'"');

可能需要一些额外的检查和优化

于 2012-07-16T14:02:51.820 回答