我有一个数据库表,其中包含字典中的单词。
现在我想为字谜选择单词。例如,如果我提供字符串SEPIAN
,则应该提取apes
,pain
,pains
,pies
,pines
,{{1}等值等等。
为此,我使用了查询
sepia
但是这个查询会返回像SELECT * FROM words WHERE word REGEXP '^[SEPIAN]{1,6}$'
,anna
这样的单词,这些单词的重复字符不在提供的字符串中。例如。 essen
有两个anna
,但搜索字符串n
中只有一个n
。
如何编写正则表达式来实现此目的?此外,如果我的搜索字符串中有重复的字符,那么重复的字符应反映在结果中。
答案 0 :(得分: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
(总共2个N
s),您的查询将变为:
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}'
答案 1 :(得分: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.'"');
可能需要进行一些额外的检查和优化