일부 시작 위치에서 문자열에서 패턴의 첫 번째 발생을 어떻게 찾을 수 있습니까?
문제
임의의 길이가 많고 위치 P0에서 시작하여 세 가지 3 글자 패턴 중 하나의 첫 번째 발생을 찾아야합니다.
문자열에는 글자 만 포함되어 있다고 가정합니다. 위치 P0에서 시작하여 'AAA'또는 'BBB'또는 'CCC'가 처음 발생할 때까지 트리플렛에서 뛰어 내리는 트리플렛 수를 찾아야합니다.
이것은 재생을 사용하는 것도 가능합니까?
해결책
Moritz는 이것이 Regex보다 빠를 수 있다고 말합니다. 조금 느려도 오전 5시에 이해하기가 더 쉽습니다. :)
#0123456789.123456789.123456789. my $string = "alsdhfaaasccclaaaagalkfgblkgbklfs"; my $pos = 9; my $length = 3; my $regex = qr/^(aaa|bbb|ccc)/; while( $pos < length $string ) { print "Checking $pos\n"; if( substr( $string, $pos, $length ) =~ /$regex/ ) { print "Found $1 at $pos\n"; last; } $pos += $length; }
다른 팁
$string=~/^ # from the start of the string
(?:.{$p0}) # skip (don't capture) "$p0" occurrences of any character
(?:...)*? # skip 3 characters at a time,
# as few times as possible (non-greedy)
(aaa|bbb|ccc) # capture aaa or bbb or ccc as $1
/x;
(P0이 0 기반이라고 가정).
물론, 문자열에서 substr을 사용하여 앞으로 건너 뛰는 것이 더 효율적일 것입니다.
substr($string, $p0)=~/^(?:...)*?(aaa|bbb|ccc)/;
당신은 실제로 regexes로 계산할 수는 없지만 다음과 같은 일을 할 수 있습니다.
pos $string = $start_from;
$string =~ m/\G # anchor to previous pos()
((?:...)*?) # capture everything up to the match
(aaa|bbb|ccc)
/xs or die "No match"
my $result = length($1) / 3;
그러나 나는 substr ()와 포장 ()을 사용하여 트리플으로 나누고 트리플을 for-loop로 걸어가는 것이 조금 더 빠르다고 생각합니다.
(편집 : lenght ()가 아닌 길이 () ;-)
이것의 주요 부분은 분할 /(...)/입니다. 그러나이 결국, 당신은 당신의 위치와 발생 데이터를 갖게 될 것입니다.
my @expected_triplets = qw<aaa bbb ccc>;
my $data_string
= 'fjeidoaaaivtrxxcccfznaaauitbbbfzjasdjfncccftjtjqznnjgjaaajeitjgbbblafjan'
;
my $place = 0;
my @triplets = grep { length } split /(...)/, $data_string;
my %occurrence_for = map { $_, [] } @expected_triplets;
foreach my $i ( 0..@triplets ) {
my $triplet = $triplets[$i];
push( @{$occurrence_for{$triplet}}, $i ) if exists $occurrence_for{$triplet};
}
또는 REGEX의 간단한 계산을 위해 (실험을 사용합니다 (?? {}).
my ( $count, %count );
my $data_string
= 'fjeidoaaaivtrxxcccfznaaauitbbbfzjasdjfncccftjtjqznnjgjaaajeitjgbbblafjan'
;
$data_string =~ m/(aaa|bbb|ccc)(??{ $count++; $count{$^N}++ })/g;
속도가 심각한 관심사 인 경우, 3 줄이 무엇인지에 따라 트리를 만들어 정말 멋진 일을 할 수 있습니다 (예 : AHO-CORASICK 알고리즘 또는 이와 유사한).
가능한 모든 상태에 대한 맵이 가능합니다 (예 : 상태) [0] [ 'a'] = 0 문자열이 'a'로 시작되지 않으면.