【问题标题】:Check if string has any consecutive repeating substring in it检查字符串中是否有任何连续的重复子字符串
【发布时间】:2013-05-31 13:33:30
【问题描述】:

我只想接受没有任何子字符串连续重复三次的字符串。子字符串事先不知道。例如,“a4a4a4123”包含“a4”; “abcdwwwabcd” - “w”; "abcde" - 有效,没有三次重复。

我尝试自己实现它,但这仅适用于带有一个字母的子字符串:

public bool IsValid(string password)
{
    var validate = true;
    char lastLetter = ' ';
    var count = 1;

    for (int pos = 0; pos < password.Length; pos++)
    {
        if (password[pos] == lastLetter)
        {
            count++;

            if (count > 2)
            {
                validate = false;
                break;
            }
        }
        else
        {
            lastLetter = password[pos];
            count = 1;
        }
    }

    return validate;
}

【问题讨论】:

  • 你有什么尝试吗?
  • 你想写这个:bool containsSubstringThreeTimes(string, substring) 还是这个:string[] substringsContainedThreeOrMoreTimes(string)?因为它们是非常不同的算法。
  • Soner Gönül,是的,我已经更新了我的问题。
  • Patashu,我需要第二个 substringsContainedThreeOrMoreTimes(string)
  • 这听起来很难。我会尝试变得贪婪:生成每个长度小于或等于大字符串三分之一的子字符串,并匹配大字符串中的子字符串。根据想要的性能,这可能或不实用:对于 15 个字母的长度,这加起来是 4943 个子字符串,然后您都必须搜索。

标签: c# string


【解决方案1】:

试试这个:

bool result = Regex.IsMatch(input, @".*(.+).*\1.*\1.*");

基本上,它会检查一个或多个字符的模式是否在同一字符串中出现 3 次或更多次。

完整解释:

首先,它匹配字符串开头的 0 个或多个字符。然后它捕获一组一个或多个。然后它匹配 0 个或更多,然后再次匹配该组。然后再次 0 次或更多次,然后再次捕获。然后又是 0 个或更多。

如果你要求字符串是连续的,试试这个:

bool result = Regex.IsMatch(input, @".*(.+)\1\1.*");

还有一些性能测试结果:

Non-consecutive: 312ms
Consecutive: 246ms

用这个程序完成了测试:

using System;
using System.Diagnostics;
using System.Text.RegularExpressions;

class Program
{
    public static void Main(string[] args)
    {
        string input = "brbrbr";
        Regex one = new Regex(@".*(.+).*\1.*\1.*");
        for (int i = 0; i < 5; i++)
        {
            bool x = one.IsMatch(input); //warm regex up
        }
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 100000; i++)
        {
            bool x = one.IsMatch(input);
        }
        sw.Stop();
        Console.WriteLine("Non-consecutive: {0}ms", sw.ElapsedMilliseconds);
        Regex two = new Regex(@".*(.+)\1\1.*");
        for (int i = 0; i < 5; i++)
        {
            bool x = two.IsMatch(input); //warm regex up
        }
        Stopwatch sw2 = Stopwatch.StartNew();
        for (int i = 0; i < 100000; i++)
        {
            bool x = two.IsMatch(input);
        }
        sw.Stop();
        Console.WriteLine("Consecutive: {0}ms", sw2.ElapsedMilliseconds);
        Console.ReadKey(true);
    }
}

【讨论】:

  • 如果您要求三重匹配是连续的,正则表达式是否更简单/更快?
  • @Patashu 不确定是否更快,要做一些性能测试。马上回来:)。但绝对更简单,主要是因为你摆脱了很多.*
  • 字符串有连续要求。我认为这会起作用'@".*(.+)\1\1.*"'。不过我不确定。
  • @MatthewWatson 我的第一个会这样做,因为它有 3 个 a。新的和它不匹配。 :)
  • 这是一个有趣的例子,说明所谓的“正则”表达式与此无关。根据定义,常规语言可以被具有固定可用存储量的程序匹配,但是这种模式匹配器可以“记住”任意长的子字符串。
【解决方案2】:

正则表达式是我攻击这个的方式:

static void Main(string[] args)
        {
            string text = "C# is the best language there is in the world.";
            string search = "the";
            Match match = Regex.Match(text, search);
            Console.WriteLine("there was {0} matches for '{1}'", match.Groups.Count, match.Value);
            Console.ReadLine();
        }

How to find multiple occurrences with regex groups?

【讨论】:

  • 他没有string search 作为输入
  • OP 更新了他的问题。这不再是一个有效的答案。
【解决方案3】:
Regex.Matches( "a4a4a4123",  "a4" ).Count >= 3

【讨论】:

  • OP 更新了他的问题。这不再是一个有效的答案。
  • 我不认为子字符串是作为输入给出的。问题是识别字符串中出现 3 次或更多次的所有子字符串。
猜你喜欢
  • 2017-02-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-26
相关资源
最近更新 更多