C语言编写如何进行模糊查找:使用字符串匹配算法、正则表达式库、模糊搜索算法。使用字符串匹配算法是最常见的方法,它可以通过部分匹配来查找目标字符串。正则表达式库提供了更强大的功能,可以匹配复杂的模式。模糊搜索算法则更加灵活,允许一定程度的错误和模糊匹配。
模糊查找是一种在不完全匹配的情况下查找字符串的方法,非常适用于需要在大数据集中进行搜索或在用户输入有误时提供建议的应用场景。下面,我们将详细探讨这几种方法及其实现。
一、使用字符串匹配算法
字符串匹配算法是模糊查找的基础。常见的字符串匹配算法有KMP算法、Boyer-Moore算法和Rabin-Karp算法。
1、KMP算法
KMP算法(Knuth-Morris-Pratt)是一种线性时间复杂度的字符串匹配算法,它通过预处理模式字符串来加速匹配过程。
实现步骤:
- 预处理模式字符串:创建部分匹配表(Partial Match Table)。
- 匹配过程:使用部分匹配表来进行快速匹配。
#include <stdio.h>
#include <string.h>
// 创建部分匹配表
void computeLPSArray(char* pat, int M, int* lps) {
int len = 0;
lps[0] = 0;
int i = 1;
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
}
// KMP 模式匹配算法
void KMPSearch(char* pat, char* txt) {
int M = strlen(pat);
int N = strlen(txt);
int lps[M];
computeLPSArray(pat, M, lps);
int i = 0; // txt的索引
int j = 0; // pat的索引
while (i < N) {
if (pat[j] == txt[i]) {
j++;
i++;
}
if (j == M) {
printf("Found pattern at index %dn", i - j);
j = lps[j - 1];
} else if (i < N && pat[j] != txt[i]) {
if (j != 0) {
j = lps[j - 1];
} else {
i = i + 1;
}
}
}
}
int main() {
char txt[] = "ABABDABACDABABCABAB";
char pat[] = "ABABCABAB";
KMPSearch(pat, txt);
return 0;
}
2、Boyer-Moore算法
Boyer-Moore算法是一种更高效的字符串匹配算法,它通过逆向匹配和模式预处理来加速匹配过程。它主要使用两个预处理表:坏字符表和好后缀表。
实现步骤:
- 预处理坏字符表:记录字符在模式中出现的最右位置。
- 预处理好后缀表:记录模式中后缀的匹配情况。
- 匹配过程:根据坏字符表和好后缀表进行匹配。
#include <stdio.h>
#include <string.h>
#define NO_OF_CHARS 256
void badCharHeuristic(char *str, int size, int badchar[NO_OF_CHARS]) {
int i;
for (i = 0; i < NO_OF_CHARS; i++)
badchar[i] = -1;
for (i = 0; i < size; i++)
badchar[(int) str[i]] = i;
}
void search(char *txt, char *pat) {
int m = strlen(pat);
int n = strlen(txt);
int badchar[NO_OF_CHARS];
badCharHeuristic(pat, m, badchar);
int s = 0;
while (s <= (n - m)) {
int j = m - 1;
while (j >= 0 && pat[j] == txt[s + j])
j--;
if (j < 0) {
printf("Pattern occurs at shift = %dn", s);
s += (s + m < n) ? m - badchar[txt[s + m]] : 1;
} else {
s += max(1, j - badchar[txt[s + j]]);
}
}
}
int main() {
char txt[] = "ABAAABCD";
char pat[] = "ABC";
search(txt, pat);
return 0;
}
二、使用正则表达式库
正则表达式是一种强大的字符串匹配工具,C语言中常用的正则表达式库有PCRE(Perl Compatible Regular Expressions)和POSIX正则表达式。
1、PCRE库
PCRE库提供了与Perl兼容的正则表达式功能,支持复杂的模式匹配。
安装PCRE库:
在Linux系统中,可以使用以下命令安装PCRE库:
sudo apt-get install libpcre3 libpcre3-dev
使用PCRE库进行正则表达式匹配:
#include <pcre.h>
#include <stdio.h>
#include <string.h>
void searchPattern(const char* pattern, const char* subject) {
pcre* re;
const char* error;
int erroffset;
int ovector[30];
re = pcre_compile(pattern, 0, &error, &erroffset, NULL);
if (!re) {
printf("PCRE compilation failed at offset %d: %sn", erroffset, error);
return;
}
int rc = pcre_exec(re, NULL, subject, strlen(subject), 0, 0, ovector, 30);
if (rc < 0) {
printf("Pattern not foundn");
} else {
printf("Pattern found at offset %dn", ovector[0]);
}
pcre_free(re);
}
int main() {
const char* pattern = "AB.C";
const char* subject = "ABC ABCD ABDC";
searchPattern(pattern, subject);
return 0;
}
2、POSIX正则表达式
POSIX正则表达式是标准C库的一部分,提供了基本的正则表达式功能。
使用POSIX正则表达式进行模式匹配:
#include <regex.h>
#include <stdio.h>
#include <string.h>
void searchPattern(const char* pattern, const char* subject) {
regex_t regex;
int reti;
char msgbuf[100];
reti = regcomp(®ex, pattern, 0);
if (reti) {
fprintf(stderr, "Could not compile regexn");
return;
}
reti = regexec(®ex, subject, 0, NULL, 0);
if (!reti) {
puts("Match");
} else if (reti == REG_NOMATCH) {
puts("No match");
} else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %sn", msgbuf);
}
regfree(®ex);
}
int main() {
const char* pattern = "AB.C";
const char* subject = "ABC ABCD ABDC";
searchPattern(pattern, subject);
return 0;
}
三、使用模糊搜索算法
模糊搜索算法允许一定程度的错误和模糊匹配,常见的模糊搜索算法包括Levenshtein距离和Double Metaphone算法。
1、Levenshtein距离
Levenshtein距离用于计算两个字符串之间的编辑距离,即将一个字符串转换为另一个字符串所需的最少操作数。
实现步骤:
- 初始化距离矩阵:创建一个二维数组记录编辑距离。
- 计算编辑距离:根据插入、删除和替换操作更新距离矩阵。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int min(int a, int b, int c) {
if (a <= b && a <= c) return a;
if (b <= a && b <= c) return b;
return c;
}
int levenshtein(const char *s1, const char *s2) {
int len1 = strlen(s1);
int len2 = strlen(s2);
int d = (int )malloc((len1 + 1) * sizeof(int *));
for (int i = 0; i <= len1; i++) {
d[i] = (int *)malloc((len2 + 1) * sizeof(int));
}
for (int i = 0; i <= len1; i++) {
d[i][0] = i;
}
for (int j = 0; j <= len2; j++) {
d[0][j] = j;
}
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
int cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1;
d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
}
}
int distance = d[len1][len2];
for (int i = 0; i <= len1; i++) {
free(d[i]);
}
free(d);
return distance;
}
int main() {
const char *s1 = "kitten";
const char *s2 = "sitting";
printf("Levenshtein distance: %dn", levenshtein(s1, s2));
return 0;
}
2、Double Metaphone算法
Double Metaphone算法是用于模糊音素匹配的算法,它可以将单词转换为其音素编码,从而实现音素级别的模糊匹配。
实现步骤:
- 转换单词为音素编码:根据发音规则将单词转换为音素编码。
- 进行音素匹配:比较两个单词的音素编码。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// Double Metaphone implementation
void doubleMetaphone(const char *word, char *primary, char *secondary) {
// Simplified version for demonstration purposes
int len = strlen(word);
int i = 0;
while (i < len) {
switch (toupper(word[i])) {
case 'A': case 'E': case 'I': case 'O': case 'U': case 'Y':
primary[i] = 'A';
secondary[i] = 'A';
break;
case 'B':
primary[i] = 'B';
secondary[i] = 'B';
break;
case 'C':
primary[i] = 'K';
secondary[i] = 'K';
break;
// Add more rules as needed
default:
primary[i] = word[i];
secondary[i] = word[i];
break;
}
i++;
}
primary[i] = '