Beiyou 22 Xintong: (13) Chapter 3 3.4 String Implementation KMP Algorithm

A Beiyou 22 Xintong~   

Code and articles on data structures and algorithms are updated weekly following the progress of the course 

Continue to pay attention to the author to unlock more exclusive codes of Youyuan Xintong~

Previous article:

Next article:

***illustrate***

1. This code is written in combination with the linear table in Chapter 2 of the book and the 4.3.3KMP algorithm.

2. The fundamental reason for speeding up the matching speed: the prefix substring does not need to be matched .

3. Regarding the buffer issue of applying for a dynamic array in the heap area :

        Every time you apply for heap space, the system will automatically use the unused heap space in the application form as a data buffer. In layman's terms, the system will predict the area in advance for the data you are about to input, and see if you enter the data again. Will it cause data overflow.

        The program is very afraid that this kind of thing will happen, so it always carefully sets aside a data buffer. Every time you input data, the data will enter the buffer generated when the data was input last time, and then the buffer will move backward; until the buffer When the area reaches the lowest end of the requested heap space, the program will issue a warning. If you don't consider applying for a little more heap space, the data will overflow! ! ! Then it will draw a little green line under the sentence for you... So! ! ! Appropriately apply for more space ! ! !

4. The implementation process in the KMP function is similar to the BF algorithm. If you understand BF, you will naturally understand KMP easily, so the focus is on the getnextarray function written earlier.

***END OF EXPLAIN***

1. Sequence table implements KMP algorithm

KMP algorithm part:

template<class temp>
void seqlist<temp>::getnextarray(seqlist<temp>& t, int*& next)
{
	next = new int[t.getlength() + 10];
	/*如果写成next = new int[t.getlength() + 1]会有建议提示:
	“写入next时缓存区溢出”,原因如下:
	next动态数组缓冲区溢出动态数组基本全部被占满,数据缓冲区不够;
	所以应多给动态数组分配一点存储空间以增加缓存区容量*/
	next[1] = 0;
	next[2] = 1;
	int p = 1;
	for (int j = 3; j <= t.getlength(); ++j)
	{
		while (p > 1 && t.get(p) != t.get(j - 1))
			p = next[p];
		if (t.get(p) == t.get(j - 1))
			++p;
		next[j] = p;
	}
}

template<class temp>
int seqlist<temp>::KMP(seqlist<temp>& t)
{
	int* next;
	getnextarray(t, next);
	int i = 1, j = 1;
	while (i <= this->getlength() && j <= t.getlength())
	{
		if (get(i) == t.get(j))
		{
			i++; j++;
		}
		else if (!next[j])
		{
			i++; j = 1;
		}
		else
			j = next[j];
	}
	delete[]next;
	if (j > t.getlength())return i + 1 - j;
	else return -1;
}

Code part and running result:

#include <iostream>
using namespace std;
#define N 100
template<class temp>
class seqlist
{
private:
	temp data[N];
	int length;
public:
	seqlist() { length = 0; }
	seqlist(temp a[], int n);
	int getlength() { return length; }
	void printlist();
	void insert(int i, temp x);
	temp del(int i);
	temp get(int i);
	int locate(temp x);
	void getnextarray(seqlist<temp>& t, int*& next);
	int KMP(seqlist<temp>& t);
};

template <class temp>
seqlist<temp>::seqlist(temp a[], int n)
{
	if (n > N)throw "数组长度超过顺序表最大长度";
	for (int i = 0; i < n; i++)
		this->data[i] = a[i];
	this->length = n;
}

template<class temp>
void seqlist<temp>::printlist()
{
	cout << "按序号依次遍历线性表中各个数据元素:" << endl;
	for (int i = 0; i < this->length; i++)
		this->data[i].print();
	cout << endl;
}

template<class temp>
void seqlist<temp>::insert(int i, temp x)
{
	if (this->length >= N)throw"上溢异常";
	if (i < 1 || i >= this->length + 1)throw"位置异常";
	for (int j = this->length; j >= i; j--)
		this->data[j] = this->data[j - 1];
	this->data[i - 1] = x;
	this->length++;
}

template<class temp>
temp seqlist<temp>::del(int i)
{
	if (this->length == 0)throw"下溢异常";
	if (i<1 || i>this->length)throw"位置异常";
	temp x = data[i - 1];
	for (int j = i; j < this->length; j++)
		data[j - 1] = data[j];
	this->length--;
	return x;
}


template<class temp>
temp seqlist<temp>::get(int i)
{
	if (i<1 || i>this->length)throw"查找位置非法";
	return this->data[i - 1];
}

template<class temp>
int seqlist<temp>::locate(temp x)
{
	for (int i = 0; i < this->length; i++)
		if (this->data[i] == x)return(i + 1);
	return 0;
}

template<class temp>
void seqlist<temp>::getnextarray(seqlist<temp>& t, int*& next)
{
	next = new int[t.getlength() + 10];
	/*如果写成next = new int[t.getlength() + 1]会有建议提示:
	“写入next时缓存区溢出”,原因如下:
	next动态数组缓冲区溢出动态数组基本全部被占满,数据缓冲区不够;
	所以应多给动态数组分配一点存储空间以增加缓存区容量*/
	next[1] = 0;
	next[2] = 1;
	int p = 1;
	for (int j = 3; j <= t.getlength(); ++j)
	{
		while (p > 1 && t.get(p) != t.get(j - 1))
			p = next[p];
		if (t.get(p) == t.get(j - 1))
			++p;
		next[j] = p;
	}
}

template<class temp>
int seqlist<temp>::KMP(seqlist<temp>& t)
{
	int* next;
	getnextarray(t, next);
	int i = 1, j = 1;
	while (i <= this->getlength() && j <= t.getlength())
	{
		if (get(i) == t.get(j))
		{
			i++; j++;
		}
		else if (!next[j])
		{
			i++; j = 1;
		}
		else
			j = next[j];
	}
	delete[]next;
	if (j > t.getlength())return i + 1 - j;
	else return -1;
}

int main()
{
	system("color 0A");
	char a[] = "hello world";
	char b[] = "good";
	char c[] = "ello";
	seqlist<char>seqa(a, strlen(a));
	seqlist<char>seqb(b, strlen(b));
	seqlist<char>seqc(c, strlen(c));
	cout << seqa.KMP(seqa) << endl;//1
	cout << seqa.KMP(seqb) << endl;//-1
	cout << seqa.KMP(seqc) << endl;//2
	return 0;
} 

"Hey blogger, are you missing a main title and content?"

"No no no no!" (with confidence) (run away)

I'll update when I wake up... 

Guess you like

Origin blog.csdn.net/bc202205/article/details/130220095