【问题标题】:regular expression to find the longest recurring character sequence in a line正则表达式查找一行中最长的重复字符序列
【发布时间】:2010-12-02 13:48:01
【问题描述】:

如何编写正则表达式来查找一行中最长的重复字符序列?

【问题讨论】:

  • 你没有。您只需使用循环或其他方式沿线扫描。为什么要为此使用正则表达式?
  • 只是为了搅浑水; 换行符算作字符吗?如果他们这样做,您希望\r\n 计为两个还是您的平台仅使用\n
  • @Aadith:该工作的工具错误。你不用尺子来测量速度,也不用浴室秤来测量温度。
  • @stillstanding:这个让我笑了:)
  • 试图利用 notepad++ 中的正则表达式搜索功能来查找文件中的某些模式.. 对为此编写程序并不感兴趣

标签: regex


【解决方案1】:

您可以使用正则表达式/(.)\1*/找到所有相关的字符序列。

最好使用正则表达式以外的工具来查找最长的此类序列。

【讨论】:

  • 由于 * 量词,这将找到 所有 个字符。你需要一个 +。
  • @neo2862:这是故意的 - (非空)字符串中最长的重复字符序列理论上可以有长度 1。例如,您可以使用我给出的正则表达式来首先找到相关子串,然后使用普通程序代码找到最长的那个。仅当您使用 * 而不是 + 时才有效。
  • @Mark Byers:单次出现是重复序列吗?我很好奇。我的意思是......它并没有真正重复,是吗?
  • 我认为“重复”意味着至少有两个相同的字符。
  • @neo2862:好的,我将“重复”改为“相关”,但不是毫无意义的术语讨论,让我们谈谈 OPs 问题。如果输入字符串是“aaa”,答案是 3。如果输入字符串是“aa”,答案是 2。如果输入字符串是“a”,答案是什么?如果您认为它是 0/未定义,请使用 +。如果您认为它是 1,请使用 +。
【解决方案2】:

在循环中这样做是最简单的:

#!/usr/bin/perl
my $string = "this aaa and bbbb for ### ## ppppppp";
my $max = "";
while ($string =~ /((.)\2+)/gs) {
    $max = $1 if length($1) > length($max);
}
print "$max\n";

您也可以使用reduce,但效率较低:

#!/usr/bin/perl
use List::Util "reduce";
my $string = "this aaa and bbbb for ### ## ppppppp";
my $max = reduce { length($b) > length($a) ? $b : $a } "", 
                    $string =~ /((.)\2+)/gs;
print "$max\n";

如果您只希望在一项作业中使用它,那很简单:

#!/usr/bin/perl
my $string = "this aaa and bbbb for ### ## ppppppp";
my $max = ( sort { length($b) <=> length($a) } "", $string =~ /((.)\2+)/g)[0];
print "$max\n";

所有三个答案都会为该示例字符串生成ppppppp

如果没有这样的序列,它们也会返回空字符串,如果出现平局,它们会首先返回这样的序列。

【讨论】:

    【解决方案3】:

    您可以执行以下正则表达式来查找重复字符:

    (.)\1+
    

    但应该使用您的编程语言来正确确定最长匹配。

    【讨论】:

      【解决方案4】:

      你没有,不可能将诸如“最长”之类的状态放入正则表达式中。您唯一能做的就是制作一个正则表达式,并让它与序列匹配。如果匹配,获取重复字符的长度,并制作一个更长的正则表达式来匹配更多的字符。在找到匹配项的同时继续执行此操作。
      这是为文本编写一个简单的解析器的愚蠢选择。

      解析器可能是伪代码:

      for(i = beginning to end, i++) {
       recurring_length = recurring(i, 1);
       if(recurring_length > max)
           max = recurring_length;
      }
      
      function recurring(i, length) {
         if(i+1 != EOF && (character at i == character i+1) )
             return recurring(i+1, length + 1);
         else return length;
      }
      

      【讨论】:

      • 请注意,这是一种效率低下的算法,可以通过一些重要的方式进行优化,这只是一个说明
      • 永远不要说永远:Perl 讨厌“不能”这个词。 ☺ 我可以当然在一个完全包含的 Perl 正则表达式中做到这一点。不过,我更喜欢使用混合方法。
      • 不可能在常规语法中对字符的可变有限重复进行建模。因此,您不能使用正则表达式来映射它。请注意,在您的 perl 示例中,您仍然需要其他控制流,例如循环等。
      【解决方案5】:

      这是在 Python 中的实现方式(不需要正则表达式):

      >>> str = 'iamastriiiiiingwaitwaaaaaaaaaaaaaatttt'
      >>> lchar = ''
      >>> longest = 0
      >>> cnt = 1
      >>> for i in str:
          if lchar == i:
              cnt += 1
          else:
              cnt = 1
          if cnt > longest:
              longest = cnt
              longchar = i
          lchar = i
      
      >>> longchar
      'a'
      >>> longest
      14
      

      如果你想将它存储在一个字符串中(很简单):

      >>> string = ''
      >>> for x in range(longest):
          string += longchar
      
      >>> string
      'aaaaaaaaaaaaaa'
      

      【讨论】:

        【解决方案6】:

        你可以试试这个:

        #!/usr/bin/perl
        use 5.10.1;
        use strict;
        use warnings;
        use Data::Dumper;
        
        my $str = 'ahhhhhhhhhhjjjjjjjiiiieeeeeeeeeeeeeeei';
        my ($char, $long) = ('',0);
        while($str=~/(.)\1*/g) {
            if (length $& > $long) {
                $long = length$&;
                $char = $1,
            }
        }
        say "$char : $long";
        

        输出:

        e : 15
        

        【讨论】:

          猜你喜欢
          • 2017-03-15
          • 1970-01-01
          • 2021-07-29
          • 2011-04-23
          • 2012-02-28
          • 1970-01-01
          • 2017-04-05
          • 2012-03-02
          • 1970-01-01
          相关资源
          最近更新 更多