如何在字符串中找到模式?

问题描述 投票:-1回答:4

所以想象你有这样的字符串

o7o7o7o7o7o

有一个明显的o7o模式,我的方法是在第一个之后找到第二个o,这将是模式,然后看看它是否匹配。

字符串是,如何获得第二个o的索引?

我试过这个

var pattern = "o7o7o7o7o7o";
var index = input.IndexOf("*");

但这显然会得到它发现的第一个o的第一个索引,我想得到第二个。我怎么做?

c# .net string algorithm pattern-matching
4个回答
1
投票

你可以做很多种方式,最快的方法就是循环:

string pattern = "o7o7o7o7o7o";
int count = 0;
int index = 0;
while(index < pattern.Length)
{
     if(pattern[index] == 'o') count++;
     if(count == 2) break;
     index++;
}

index是你想要的。

LINQ:

int index = pattern.Select((x, i) => new { x, i })
              .Where(a => a.x == 'o').Skip(1)
              .FirstOrDefault().i;

string.IndexOf():

int count = 0, index = 0;
do
{
    index = pattern.IndexOf('o', index);
    if (index != -1) { count++; index++; }
} while (index != -1 && count < 2);

还有很多其他的方法,但我认为上面的三个例子会很好,因为我想到的其他方式都比较慢(在我能想到的那些方面)。


1
投票

也可以这样使用正则表达式:

var pattern = "o7o7o7o7o7o";

var regex = new Regex("7(o)");

var matches = regex.Matches(pattern);

foreach (Match match in matches)
{
    Console.WriteLine(match.Groups[1].Index);
}

0
投票

构建前缀函数并查找压缩表示为described here

给定长度为n的字符串s。我们想要找到字符串的最短“压缩”表示,即我们想要找到最小长度的字符串t,使得s可以表示为t的一个或多个副本的串联。

很明显,我们只需要找到t的长度。知道长度,问题的答案将是具有此长度的s的前缀。

让我们计算s的前缀函数。使用它的最后一个值,我们定义值k = n-π[n-1]。我们将证明,如果k除以n,则k将是答案,否则不存在有效压缩,答案为n。

但是你的字符串不能表示为(u)^ w,因为它最后有过多的char。在这种情况下,通过(i+1)检查(i-p[i])(i是指数)的可分性

对于s = '1231231231',我们可以得到(123)^3+1的代表,因为(i+1)可以整除的最后一个k[i]=3是9

  i+1: p[i] k[i]
  1 : 0  1 
  2 : 0  2 
  3 : 0  3 
  4 : 1  3 
  5 : 2  3 
  6 : 3  3 
  7 : 4  3 
  8 : 5  3 
  9 : 6  3 
  10 : 7  3 

0
投票

要获得o第二次出现的索引,当至少应该有一次o时,你可以使用一个使用捕获组的正则表达式获取该组的索引:

^[^o]*o[^o]+(o)

这将匹配:

  • ^断言字符串的开头
  • [^o]*匹配0+次而不是使用否定字符类的o
  • o字面匹配o
  • [^o]+匹配1次以上不是使用否定字符类的o(如果还可以连续2个o,则使用[^o]*)。
  • (o)在一组中捕获o

Regex demo

string pattern = @"^[^o]*o[^o]+(o)";
string input = @"o7o7o7o7o7o";

Match m = Regex.Match(input, pattern);
Console.WriteLine(m.Groups[1].Index); // 2

Demo c#

© www.soinside.com 2019 - 2024. All rights reserved.