KMP字符串匹配算法陷入循环

时间:2015-02-02 02:11:02

标签: java string algorithm

我尝试使用CLRS实现KMP字符串匹配算法,但文本输入为" bbaa"并且模式输入为" aab",它被卡在while函数内的getKMPPrefix循环中的无限循环中。我的代码如下:

private int[] getKMPPrefix(char[] p, int m) {
    int[] prefix = new int[m];
    prefix[0] = 0;
    int k = 0;
    for(int q = 1; q < m; q++) {
        while(k > 0 && p[k] != p[q] ) { //Stuck here
            k = prefix[k];
        }
        if(p[k] == p[q]) {
            k++;
        }
        prefix[q] = k;
    }
    return prefix;
}

public void kmp(String text, String pattern) {
    char[] t = text.toCharArray();
    char[] p = pattern.toCharArray();
    int n = text.length();
    int m = pattern.length();

    int[] prefix = getKMPPrefix(p, m);

    int q = 0;
    for(int i = 1; i < n; i++) {
        while(q > 0 && p[q] != t[i]) {
            q = prefix[q];
        }
        if(p[q] == t[i]) {
            q++;
        }
        if(q == m) {
            System.out.println("Pattern occurs with shift " + (i-m+1));
            q = prefix[m-1];
        }
    }
}

知道为什么会这样吗?

2 个答案:

答案 0 :(得分:2)

以下是发生的事情:

它到达了这条线:

while(k > 0 && p[k] != p[q] ) { //Stuck here

k=0显然这会失败,它会跳出循环并转到下一个

if(p[k] == p[q]) {
            k++;
        }

在您的情况下,输入为aab,因此这是p[0]=p[1]=a

现在,k=1

现在您将k的值分配给prefix

prefix[q] = k;

现在它陷入了僵局。

它现在回到while循环

 while(k > 0 && p[k] != p[q] ) { //Stuck here
            k = prefix[k];
        }

注意,您刚刚在早期循环prefix[q] = k;中分配,即p[1] = 1

涉及while循环k=1和&#39; p [1]!= p [2]&#39;即a!=b它通过并进入循环

k = prefix[k];

k=1prefix[1] = 1,这意味着您要将值1重新分配给k

它再次返回到k=1p=1的while循环和值,因为它永远不会超过while循环以增加p

存在死锁,true循环的条件将保持while,并且程序永远不会出现while循环。

您可以更改while循环条件或在循环内部增加p或在某些条件之后增加break内部。我解释了Deadlock,尝试自己弄清楚程序。古德勒克

答案 1 :(得分:0)

// Tint the image
- (UIImage *)imageWithTint:(UIColor *)tintColor alpha:(CGFloat)alpha {
    UIImage *image = self;
    CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, [UIScreen mainScreen].scale);
    CGContextRef c = UIGraphicsGetCurrentContext();

    [image drawInRect:rect];
    CGContextSetFillColorWithColor(c, [[tintColor colorWithAlphaComponent:0.25] CGColor]);
    CGContextSetBlendMode(c, kCGBlendModeSourceAtop);
    CGContextFillRect(c, rect);

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return result;
}

如果模式是&#34; aabaaa&#34;,您的代码将导致死锁。这个正确的条件将以正确的方式生成前缀。