顺序表示的串——串的模式匹配2——模式匹配

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36669549/article/details/84863528


编写程序比较Brute-Force算法与KMP算法的效率。例如,主串S="bcdamnbacabaabaabacababafabacabababab",模式串T="abaabacababa",统计Brute-Force算法与KMP算法在匹配过程中的比较次数并输出模式串的next值。


【分析】

通过主串的模式匹配比较Brute-Force算法与KMP算法的效果。朴素的Brute-Force算法也是常用的算法,毕竟它不需要计算next函数值。KMP算法在模式串与主串存在许多部匹配的情况下,其优越性才会显示出来。
SeqString.h

#pragma once
#include <iostream>
using namespace std;
#define MAXSIZE 100
#define MaxLen 50
//存储结构
typedef struct 
{
	char str[MAXSIZE];
	int Length;
}SeqString;
//串的赋值
void StrAssign(SeqString  *S, char cstr[])
{
	int i=0;
	for (i = 0; cstr[i] != '\0';i++)
	{
		S->str[i] = cstr[i];
	}
	S->Length = i;
}

//判断串是否为空
int StrEmpty(SeqString S)
{
	if (S.Length==0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

//求串的长度
int StrLength(SeqString S)
{
	return S.Length;
}

//串的复制
void StrCopy(SeqString *T, SeqString S)
{
	int i;
	for (i = 0; i < S.Length;i++)
	{
		T->str[i] = S.str[i];
	}
	T->Length = S.Length;
}
//比较两个串的大小
int StrCompare(SeqString S, SeqString T)
{
	int i;
	for (i = 0; i < S.Length&&T.Length;i++)
	{
		if (S.str[i]!=T.str[i])
		{
			return (S.str[i] - T.str[i]);
		}

	}
	return (S.Length - T.Length);
}
/*在串的第pos位置插入串T。若插入成功,返回1;否则返回0.*/
/*串的插入操作具体实现分为3种情况:
  第1种情况,在S中插入T后串长不超过能容纳的最长字符,即S->Length+T.Length<=MaxLen
则先将串S中pos后的字符向后移动Len个位置,然后将串T插入S中即可;
  第2种情况,若将T插入S后,串长超过能容纳的最长字符但T能完全插入S中,即S->Length+T.Length>MaxLen
则将串S中pos后的字符往后移动Len个位置后,S中的部分字符被舍弃;
  第3种情况,将T插入S中,有S->Length+T.Length>MaxLen且T不能完全被插入S中
则T中部分字符和S中第Len位置以后的字符均被舍弃。*/
int StrInsert(SeqString *S, int pos, SeqString T)
{
	int i;
	if (pos < 0||pos-1>S->Length)
	{
		cout << "插入位置不正确!";
		return 0;
	}
	if (S->Length + T.Length <=MaxLen)
	{
		for (i = S->Length + T.Length - 1; i >= pos + T.Length - 1;i--)
		{
			S->str[i] = S->str[i - T.Length];
		}
		for (i = 0; i < T.Length;i++)
		{
			S->str[pos + i - 1] = T.str[i];
		}
		S->Length = S->Length + T.Length;
		return 1;
	}

	else if (pos+T.Length<=MaxLen)
	{
		for (i = MaxLen - 1; i > T.Length + pos - 1;i--)
		{
			S->str[i] = S->str[i - T.Length];
		}
		for (i = 0; i < T.Length;i++)
		{
			S->str[i + pos - 1] = T.str[i];
		}
		S->Length = MaxLen;
		return 0;
	}
	else
	{
		for (i = 0; i < MaxLen - pos;i++)
		{
			S->str[i + pos - 1] = T.str[i];
		}
		S->Length = MaxLen;
		return 0;
	}
}

/*删除串S中pos开始的len个字符*/
int StrDelete(SeqString *S, int pos, int len)
{
	int i;
	if (pos<0||len<0||pos+len-1>S->Length)
	{
		cout << "删除位置不合法,参数len不合法!";
		return 0;
	}
	else
	{
		for (i = pos + len; i <= S->Length - 1;i++)
		{
			S->str[i - len] = S->str[i];
		}
		S->Length = S->Length - len;
		return 1;
	}
}

/*将串S连接在串T的末尾。串的连接操作可以分为两种情况:
第1种,连接后串长T->Length+S.Length≤MaxLen,则直接将串S连接在串T的尾部;
第2种,连接后串长T->Length+S.Length≥MaxLen且串的长度<MaxLen,则串S会有字符丢失。*/
int StrConcat(SeqString *T, SeqString S)
{
	int i, flag;
	if (T->Length+S.Length<=MaxLen)
	{
		for (i = T->Length; i < T->Length + S.Length;i++)
		{
			T->str[i] = S.str[i - T->Length];
		}
		T->Length = T->Length + S.Length;
		flag = 1;
	}
	else if(T->Length<MaxLen)
	{
		for (i = T->Length; i < MaxLen;i++)
		{
			T->str[i] = S.str[i - T->Length];
		}
		T->Length = MaxLen;
		flag = 0;
	}
	return flag;
}

/*清空串操作*/
void StrClear(SeqString *S)
{
	S->Length = 0;
}

main.cpp

#include <stdlib.h>
#include <string.h>
#include "SeqString.h"
#include <iostream>
#include <iomanip>
int B_FIndex(SeqString S,int pos,SeqString T,int *count);
int KMP_Index(SeqString S,int pos, SeqString T, int next[],int *count);
void GetNext(SeqString T,int next[]);
void PrintArray(SeqString T,int next[],int length);
void main()
{
	SeqString S, T;
	int count1 = 0, count2 = 0, find;
	int next[40];
	StrAssign(&S, "bcdamnbacabaabaabacababafabacabababab");
	StrAssign(&T, "abaabacababa");
	GetNext(T, next);
	cout << "模式串T的next和改进后的next值:" << endl;
	PrintArray(T, next, StrLength(T));
	find = B_FIndex(S, 1, T, &count1);
	if (find>0)
	{
		cout << "Brute-Force算法的比较次数为" << count1 << endl;

	}
	find = KMP_Index(S, 1, T, next, &count2);
	if (find>0)
	{
		cout << "利用next的KMP算法的比较次数为:" <<count2<< endl;
	}


	StrAssign(&S, "bcdabcacbdaacabcabaacaabcabcabcbccbcabccbdcabcb");
	StrAssign(&T, "abcabcbc");
	GetNext(T, next);
	cout << "模式串T的next和改进后的next值:" << endl;
	PrintArray(T, next, StrLength(T));
	find = B_FIndex(S, 1, T, &count1);
	if (find > 0)
	{
		cout << "Brute-Force算法的比较次数为" << count1 << endl;

	}
	find = KMP_Index(S, 1, T, next, &count2);
	if (find > 0)
	{
		cout << "利用next的KMP算法的比较次数为:" << count2 << endl;
	}


	system("pause");
}

void PrintArray(SeqString T, int next[], int length)
{
	int j;
	cout << "j:\t\t";
	for (j = 0; j < length;j++)
	{
		cout << setw(3) << j;
	}
	cout << endl;
	cout << "模式串:\t";
	for (j = 0; j < length;j++)
	{
		cout << setw(3) << T.str[j];
	}
	cout << endl;
	cout << "next[j]:\t";
	for (j = 0; j < length;j++)
	{
		cout << setw(3) << next[j];
	}
	cout << endl;
}

int B_FIndex(SeqString S, int pos, SeqString T, int *count)
{
	int i, j;
	i = pos - 1;
	j = 0;
	*count = 0;
	while (i<S.Length&&j<T.Length)
	{
		if (S.str[i]==T.str[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i - j + 1;
			j = 0;
		}
		(*count)++;
	}

	if (j>=T.Length)
	{
		return i - j + 1;
	}
	else
	{
		return -1;
	}

}


int KMP_Index(SeqString S, int pos, SeqString T, int next[], int *count)
{
	int i, j;
	i = pos - 1;
	j = 0;
	*count = 0;
	while (i<S.Length&&j<T.Length)
	{
		if (j==-1||S.str[i]==T.str[j])
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];
		}

		(*count)++;
	}
	if (j>=T.Length)
	{
		return i - T.Length + 1;
	} 
	else
	{
		return -1;
	}
}

void GetNext(SeqString T, int next[])
{
	int j, k;
	j = 0;
	k = -1;
	next[0] = -1;
	while (j<T.Length)
	{
		if (k==-1||T.str[j]==T.str[k])
		{
			j++;
			k++;
			next[j] = k;
		}
		else
		{
			k = next[k];
		}

	}
}

结果:

猜你喜欢

转载自blog.csdn.net/baidu_36669549/article/details/84863528
今日推荐