本代码中用了KMP算法、BF算法、BM算法三种算法进行字符串匹配。
文本串保存在了test.txt中,模式串需自行输入。
代码如下:
#include"stdio.h"
#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#define ASIZE 256
#define XSIZE 200
typedef struct{
char *ch;
int length;
}HString;
//BF算法
void BF(HString S,HString T)
{ int i=0,j=0;
loop:
j=-1;
while(i<S.length&&j<T.length)
{
if(S.ch[i]==T.ch[j])
{i++;j++; }
else
{ i=i-j+1; j=0;}
}
if(j==T.length)
{ printf("在位置%d发现匹配!\n",i-j+1);goto loop; }
}
//KMP算法
void KMP(HString S,HString T,int *next)
{
int i=0,j=0;
loop:
while(i<S.length&&j<T.length)
{
if(j==-1||S.ch[i]==T.ch[j])
{ ++i; ++j; }
else
j=next[j];
}
if(j==T.length)
{
printf("在位置%d发现匹配!\n",i-j+1);
j=-1;
goto loop;
}
}
void Next(HString T,int *next) //求next函数
{
int i,j=0,k=-1;
next[0]=-1;
while(j<T.length)
{
if(k==-1||T.ch[j]==T.ch[k])
{
if(T.ch[++j]==T.ch[++k]) next[j]=next[k];
else next[++j]=++k;
}
else k=next[k];
}
}
//BM算法 (Boyer-Moore) 好后缀相关函数
void preBmBc(HString Q, int m, int bmBc[]) {
int i;
for (i = 0; i <256; ++i)
bmBc[i] = m;
for (i = 0; i < m - 1; ++i)
bmBc[Q.ch[i]] = m - i - 1;
}
void suffixes(HString Q, int m, int *suff) {
int f, g, i;
suff[m - 1] = m;
g = m - 1;
for (i = m - 2; i >= 0; --i) {
if (i > g && suff[i + m - 1 - f] < i - g)
suff[i] = suff[i + m - 1 - f];
else {
if (i < g)
g = i;
f = i;
while (g >= 0 && Q.ch[g] == Q.ch[g + m - 1 - f])
--g;
suff[i] = f - g;
}
}
}
void preBmGs(HString Q, int m, int bmGs[]) {
int i, j, suff[Q.length];
suffixes(Q, m, suff);
for (i = 0; i < m; ++i)
bmGs[i] = m;
j = 0;
for (i = m - 1; i >= 0; --i)
if (suff[i] == i + 1)
for (; j < m - 1 - i; ++j)
if (bmGs[j] == m)
bmGs[j] = m - 1 - i;
for (i = 0; i <= m - 2; ++i)
bmGs[m - 1 - suff[i]] = m - 1 - i;
}
int MAX(int i,int j) //求最大值
{
if(i>j) return i;
else return j;
}
void BM(HString Q, int m, HString S, int n) {
int i, j, bmGs[Q.length], bmBc[256];
preBmGs(Q, m, bmGs);
preBmBc(Q, m, bmBc);
j = 0;
while (j <= n - m) {
for (i = m - 1; i >= 0 && Q.ch[i] == S.ch[i + j]; --i);
if (i < 0) {
printf("在位置%d发现匹配!\n",j+1);
j += bmGs[0];
}
else
j += MAX(bmGs[i], bmBc[S.ch[i + j]] - m + 1 + i);
}
}
int main()
{ HString S,Q;
FILE *fp;
if(!(fp = fopen("test.txt" , "r"))) printf("读取失败!!\n");
fseek(fp,0,SEEK_END); //查看文件大小
int file_size;
file_size=ftell(fp);
int count=0; //数出换行符数目
char ch;
fseek(fp,0,SEEK_SET);
printf("文件中的内容如下:\n");
while((ch=fgetc(fp))!=EOF)
{
if(ch=='\n') count++;
putchar(ch);
}
file_size-=count;
int i=0; //将文件中的字符写入S.ch
fseek(fp,0,SEEK_SET);
S.ch =(char *)malloc(file_size * sizeof(char));
while((ch=fgetc(fp))!=EOF)
if(ch!='\n') {S.ch[i]=ch;i++;}
S.ch[i]='\0';
S.length=file_size+1;
printf("\n请输入模式串:\n");
Q.ch =(char *)malloc(XSIZE* sizeof(char));
Q.length=0;
ch=getchar();
if(ch!='\n')
Q.ch[Q.length++]=ch;
while(ch!='\n')
{
ch=getchar();
Q.ch[Q.length++]=ch;
}
Q.ch[Q.length]='\0';
Q.length--;
int *next; //定义next数组,KMP中使用
next=(int *)malloc(Q.length*sizeof(int));
printf("---------------- BF算法 ------------------\n");
BF(S,Q); //BF算法
printf("\n---------------- KMP算法 ----------------\n");
Next(Q,next); //KMP算法
KMP(S,Q,next);
printf("\n---------------- BM算法 ------------------\n");
BM(Q,Q.length,S,S.length); //BM 算法
return 0;
}
运行结果如下: