C 长文本字符串中的模式匹配
我写了这段代码,它在某些情况下是有效的。然而,有时它会失败,我就是不明白为什么。有人能帮我找出错误吗 它适用于: 字符串:C 长文本字符串中的模式匹配,c,C,我写了这段代码,它在某些情况下是有效的。然而,有时它会失败,我就是不明白为什么。有人能帮我找出错误吗 它适用于: 字符串:ishanthakkar-ishan 模式:ishan 但它失败于: 字符串:cpr编程 模式:cpr 资料来源: #include <stdio.h> #include <stdlib.h> #include <string.h> int *compute_prefix_function(char *pattern, i
ishanthakkar-ishan
模式:ishan
但它失败于:
字符串:cpr编程
模式: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;
}
#包括
#包括
#包括
int*计算前缀函数(char*模式,int psize)
{
int k=-1;
int i=1;
int*pi=malloc(sizeof(int)*psize);
if(!pi)
返回NULL;
pi[0]=k;
对于(i=1;i-1&&pattern[k+1]!=pattern[i])
k=pi[k];
if(模式[i]==模式[k+1])
k++;
pi[i]=k;
}
返回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;
}
intkmp(char*target、inttsize、char*pattern、intpsize)
{
int i;
int*pi=计算前缀函数(模式,psize);
int k=-1;
if(!pi)
返回-1;
对于(i=0;i-1&&pattern[k+1]!=target[i])
k=pi[k];
if(目标[i]==模式[k+1])
k++;
if(k==psize-1){
自由(pi);
返回i-k;
}
}
自由(pi);
返回-1;
}
int main(int argc,const char*argv[]
{
字符目标[200];
char*ch=目标;
字符模式[20];
int i;
printf(“输入字符串:\n”);
fgets(目标,100,标准偏差);
printf(“输入要匹配的字符串:\n”);
fgets(模式,20,标准);
i=kmp(目标,strlen(目标),模式,strlen(模式));
如果(i>=0)
printf(“匹配@:%s\n”,ch+i);
getch();
返回0;
}
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。然后在调用
kmp()
之前(以及在scanf()之后)选择模式和目标
程序应该表现得更好
注意:10
是'\n'
(左)和13
是'\r'
(CR)获得线索:
i = kmp(target, strlen(target), pattern, strlen(pattern));
正在传递字符串长度+1(对于空字符),因此对某些文本字符串给出了错误结果
i = kmp(target, strlen(target)-1, pattern, strlen(pattern)-1);
适用于所有情况
谢谢你们大家抽出时间 尽量正确地缩进代码-不需要额外的空格。您能对代码进行注释以便清楚各个部分的意图吗?据我所知,像kmp()
这样的函数不是标准计算词典的一部分,您只声明程序进行“模式匹配”,而从未指定这意味着什么。据我们所知,代码可能是正确的。@John:很抱歉给您带来不便,我添加了一些描述来理解这个程序。实际上我还没有编写完整的程序,所以我也有一些困惑@JohnZwinck:kmp
在字符串算法中是明确的Knuth Morris Pratt。我在kmp()函数中犯了一些错误。因为它适用于文本字符串和模式,比如jiahkhan和jiah,对于jiah和jiahkhanI返回-1,尽管这应该可以工作!我试图删除CR和LF,但在这种情况下,它对任何情况都不起作用!你添加了chomp函数了吗?在调用kmp之前,对每个变量调用两次?它在这里工作…是的,我用另一种方式做的!感谢buddy ring0,你离我的解决方案很近:)@ring0这些应该写为LF的'\n'
,CR的'\r'
,不是吗?此外,字符串终止符更清楚地写为'\0'
@unwind Agreed for CR/LF,10和13并不那么有名。至于0
vs'\0'
,我喜欢使用0
,因为许多初学者将'\0'
视为一个特殊字符,而在C中,这只是0的1字节整数值。这有助于从C的基本原理考虑C。
i = kmp(target, strlen(target)-1, pattern, strlen(pattern)-1);