我有一点问题,我有8个字符,例如“a b c d a e f g”和一个单词列表,例如: 妈妈,爸爸,坏,fag,abac
如何检查我是否可以用我的字母组成这些单词? 在我的例子中,我可以写出坏的,abac和fag,但我不能写爸爸(我没有两个D)和妈妈(我没有M或O)。
我很确定可以使用RegEx完成,但即使在Perl中使用某些函数也会有所帮助。 先谢谢你们! :)
答案 0 :(得分:6)
这最简单地通过从要测试的单词形成正则表达式来完成。
这会对可用字符列表进行排序,并通过连接它们来形成字符串。然后将每个候选单词拆分为字符,排序并重新加入正则表达式.*
作为分隔符。因此,例如,abac
将转换为a.*a.*b.*c
。
然后通过测试派生正则表达式的可用字符串来确定单词的有效性。
use strict;
use warnings;
my @chars = qw/ a b c d a e f g /;
my $chars = join '', sort @chars;
for my $word (qw/ mom dad bad fag abac /) {
my $re = join '.*', sort $word =~ /./g;
print "$word is ", $chars =~ /$re/ ? 'valid' : 'NOT valid', "\n";
}
<强>输出强>
mom is NOT valid
dad is NOT valid
bad is valid
fag is valid
abac is valid
答案 1 :(得分:3)
首先,您需要计算可用的字符数。
然后构建你的正则表达式(这不是Perl代码!):
从输入锚的开始开始,这匹配字符串的开头(列表中的单个单词):
^
添加尽可能多的唯一字符数:
(?!(?:[^<char>]*+<char>){<count + 1>})
示例:如果(?!(?:[^a]*+a){3})
的数量为2,则a
。
我在这里使用了一个名为零宽度负向前瞻(?!pattern)
的高级正则表达式构造。它将不消耗文本,它将尽力检查字符串中的任何内容是否与指定的模式(?:[^a]*+a){3}
匹配。基本上,我的想法是检查我在字符串中找不到3'a'。如果我真的找不到'a'的3个实例,则意味着该字符串只能包含2个或更少的'a'。
请注意,我使用的*+
是0或更多量词,占有。这是为了避免不必要的回溯。
放置[]
中可能出现的字符:
[<unique_chars_in_list>]+
示例:对于a b c d a e f g
,这将变为[abcdefg]+
。这部分实际上将使用该字符串,并确保该字符串仅包含列表中的字符。
以输入锚的结尾结束,它与字符串的结尾匹配:
$
因此,对于您的示例,正则表达式将是:
^(?!(?:[^a]*+a){3})(?!(?:[^b]*+b){2})(?!(?:[^c]*+c){2})(?!(?:[^d]*+d){2})(?!(?:[^e]*+e){2})(?!(?:[^f]*+f){2})(?!(?:[^g]*+g){2})[abcdefg]+$
您还必须为不区分大小写的匹配指定i
标志。
请注意,这只考虑要匹配的单词列表中的英文字母(a-z)的情况。这里没有考虑空格和连字符。
答案 2 :(得分:1)
如何将两个字符串按字母顺序排序,然后为要检查插入的字符串排序。* 在每个字母之间如此:
'aabcdefg' =~ m/a.*b.*d.*/
True
'aabcdefg' =~ m/m.*m.*u.*/
False
'aabcdefg' =~ m/a.*d.*d.*/
False
答案 3 :(得分:0)
一些伪代码:
每个单词:
甚至更好,使用字符的频率计数。 对于可用字符,构造从字符到该字符的出现次数的映射。 对每个候选单词执行相同操作并与可用映射进行比较,如果单词映射包含可用映射不匹配的字符的映射,或者映射值在单词映射中比可用映射大,则该单词不能使用可用的字符构建。
答案 4 :(得分:0)
这是一个非常简单的脚本,很容易概括:
#!/usr/bin/env perl
use strict;
use warnings;
sub check_word {
my $word = shift;
my %chars;
$chars{$_}++ for @_;
$chars{$_}-- or return for split //, $word;
return 1;
}
print check_word( 'cab', qw/a b c/ ) ? "Good" : "Bad";
当然,如果字母列表每次都相同,那么这个函数的性能可以大大增强。实际上对于八个字符,复制哈希与每次构建一个新字符可能速度相同。
答案 5 :(得分:-2)
伪代码:
bool possible=true
string[] chars= { "a", "b", "c"}
foreach word in words
{
foreach char in word.chars
{
possible=possible && chars.contains(char)
}
}