表示为String的2D矩阵的正则表达式

时间:2013-11-03 02:45:00

标签: java regex matrix

我正在尝试在表示为字符串的2D矩阵中搜索模式。请注意以下内容:

// horizontal line
String pat1 =
    "............." +
    "............." +
    "............." +
    "....XXXX....." +
    "............." +
    ".............";

// vertical line
String pat2 =
    "............." +
    "......X......" +
    "......X......" +
    "......X......" +
    "......X......" +
    ".............";

搜索第一个模式将是微不足道的,正则表达式将是这样的:

X+

在第二种情况下,它有点棘手但可行,因为我知道矩阵的列数和行数:

(X.{`WIDTH - 1`})+

当我遇到问题想出正确的正则表达式时,试图想出一种识别以下模式的方法:

// fixed but unknown number of columns
String pat3 =
    "............." +
    ".....XXX....." +
    ".....XXX....." +
    ".....XXX....." +
    ".....XXX....." +
    ".............";

// variable number of columns
String pat4 =
    "............." +
    ".....XXX....." +
    "....XXXXX...." +
    "...XXXXXXX..." +
    ".....XXX....." +
    ".............";

我正在寻找的是一种创建等同于:

的正则表达式模式的方法
(X.{`WIDTH - PREVCOUNT`})+

PREVCOUNT是最后匹配模式的长度(我知道我会错过pat4中第4行的第一个X,但我可以忍受它)。我知道正则表达式中存在前瞻性,但我想知道我想要实现的目标是否可行。即使有可能,我也担心使用前瞻的性能,因为我不完全了解它们如何在内部工作。

有没有一种方法可以通过单一的正则表达式验证来实现,或者我必须逐行搜索,然后尝试查看X是否都是连续的?

编辑:作为澄清,我正在尝试搜索X的“blob”。只要在列/行之间存在连续的X,就可以将其视为属于blob。几个例子:

String blob1 =
    "............." +
    "......XX....." +
    "....XXXX....." +
    "...XXXXX....." +
    ".....XXX....." +
    ".............";

String blob2 =
    "............." +
    ".....XXX....." +
    "....XXXXX....." +
    "...XXXXXXX..." +
    "....XXXXX...." +
    ".....XXX.....";


String blob3 =
    "............." +
    ".....XXX....." +
    ".....XXX......" +
    ".....XXX....." +
    "............." +
    ".............";


String notblob =
    "............." +
    "..XXX........" +
    "......XXX....." +
    "..XXX........." +
    ".............." +
    ".............";

我的解决方案不需要精确,因此我尝试使用可能糟糕的正则表达式方法。

3 个答案:

答案 0 :(得分:2)

使用正则表达式无法解决此问题。

基本上,您可以定义矩阵:

0^k1 X^l1 0^m1
0^k2 X^l2 0^m2
0^k3 X^l3 0^m3

000XX000
 ^  ^ ^
 k  l m

其中,0 ^ a表示“字符'0'重复一次”,
k代表X
之前重复0 l代表重复X
m代表X
之后重复0 ki + li + mi = row_width,对于任何i

现在,您的blob标准是:

mi + k(i+1) < row_width
ki + m(i+1) < row_width
these two conditions should meet for any i

常规语言无法与这种模式匹配,它们没有内存,因此没有正则表达式解决方案来解决您的问题。


正确的解决方案将涉及连接组件计数,以确定有多少单独的组件。

答案 1 :(得分:1)

我认为一个优雅的解决方案是首先抑制水平和垂直的所有单X序列,例如:

String blob = ".....";
blob.replaceAll("([^X])X([^X])", "$1.$2")
    .replaceAll("([^X].....)X(.....[^X])","$1.$2");

然后,至少2个Xes的所有剩余序列都是斑点。 请注意,为了克服sdanzig提到的相同问题,您应首先使用非Xes的“边框”“展开”blob。

答案 2 :(得分:0)

我想我想知道你在这里要做什么。您定义的“prevcount”不足以匹配模式。您必须考虑“下一个宽度”才能确定要检查的点数。但是,我不确定你是否真的在验证那些微不足道的模式。 X +也将连续匹配5个X.在你的第二个模式中,第一行或最后一行可能是两个X,你就不会发现它。

那就是说,这是一种用pat3提供类似验证的方法:

(X{3}.{`WIDTH-3`})+

我可能通过重复X模式打破了另一个禁忌,但你需要这样做才能使重复模式与“X-block”的开始和停止保持一致。

pat4甚至比较棘手。没有真正的方法来保持您的验证顺序一次检查一行。你可以这样做:

(X{3}.{`WIDTH-4`}|X{5}.{`WIDTH-6`}|X{5}.{`WIDTH-6`}|X{3}.{`WIDTH-5`})+

但是你很容易在切换行的情况下验证矩阵,并且在X块的每一侧都改变了点以适应。但是,您可以尝试一次检查所有行:

(X{3}.{`WIDTH-4`}X{5}.{`WIDTH-6`}X{5}.{`WIDTH-6`}X{3}.{`WIDTH-5`})

这不会有任何额外的性能损失。它可能更有效率,因为你只会产生一次启动正则表达式模式编译+匹配的开销。

琐碎的旁注: 如果您使用矩阵的宽度作为多行字符串,它将无法工作。您需要添加一个,以考虑换行符。然后你需要确保你的“。”捕获换行符也是如此。在Java中,您可以使用Pattern.DOTALL。

相关问题