长文本字符串中的模式匹配

时间:2013-06-10 12:09:47

标签: c

我编写了这段代码,它在某些情况下有效。然而,有时它失败了,我只是不明白为什么。有人可以帮我发现错误吗?

适用于: 字符串:ishanthakkar ishan 啪!ishan

但它失败了:

字符串:cpr ograming 啪!cpr

来源:

#include <stdio.h>    
#include <stdlib.h>    
#include <string.h>

int *compute_prefix_function(char *pattern, int psize)
{
    int k = -1;
    int i = 1;
    int *pi = malloc(sizeof(int)*psize);
    if (!pi)
        return NULL;

    pi[0] = k;
    for (i = 1; i < psize; i++) {
        while (k > -1 && pattern[k+1] != pattern[i])
            k = pi[k];
        if (pattern[i] == pattern[k+1])
            k++;
        pi[i] = k;
    }
    return pi;
}

//此函数在O(n)时间内找到匹配的字符串,因此当找到不匹配的字符时,只遍历文本字符串一次;它继续下一个字符,并开始与要搜索的字符串的第一个字符进行比较,即模式

int kmp(char *target, int tsize, char *pattern, int psize)
{
    int i;
    int *pi = compute_prefix_function(pattern, psize);
    int k = -1;
    if (!pi)
        return -1;

    for (i = 0; i < tsize; i++) {
        while (k > -1 && pattern[k+1] != target[i])
            k = pi[k];
        if (target[i] == pattern[k+1])
            k++;

        if (k == psize - 1) {
            free(pi);
            return i-k;
        }
    }

    free(pi);
    return -1;
}

int main(int argc, const char *argv[])
{
    char target[200];
    char *ch = target;
    char pattern[20];
    int i;

    printf("Enter the string: \n");
    fgets(target,100,stdin);

    printf("Enter the string to be matched: \n");
    fgets(pattern,20,stdin);

    i = kmp(target, strlen(target), pattern, strlen(pattern)); 
    if (i >= 0)
        printf("matched @: %s\n", ch + i);

    getch();
    return 0;
}

2 个答案:

答案 0 :(得分:2)

fgets 函数读取并包含字符串中的结尾CR(或CRLF)。

添加chomp()功能,例如

void chomp(char *s) {
    int n = strlen(s);
    while (n && (s[n-1]==10 || s[n-1]==13)) s[--n] = 0;
}

删除字符串末尾的任何CR或LF 然后chomp() 模式目标,然后再调用kmp()(并在scanf()之后)

chomp(target);
chomp(pattern);

i = kmp(target, strlen(target), pattern, strlen(pattern)); 

程序应该表现得更好。


注意:10'\n'(LF),13'\r'(CR)

答案 1 :(得分:1)

有线索:

i = kmp(target, strlen(target), pattern, strlen(pattern)); 

传递字符串长度+ 1(对于空字符),因此它为某些文本字符串

提供了错误的结果
i = kmp(target, strlen(target)-1, pattern, strlen(pattern)-1); 

适用于所有情况!

感谢你们所有人的时间!