KMP algorithm (string matching) (AcWing)

The KMP algorithm is often used for string matching. Before introducing the KMP algorithm for matching, first introduce how to violently match strings.

 For two strings, use two pointers to compare in turn, the code:

for (int i = 1; i <= n; i ++ )
{
    bool flag = true;
    for (int j = 1; j <= m; j ++ )
    {
        if (s[i + j - 1] != p[j])
        {
            flag=false;
            break;
        }
    }
}

If it does not match, it is equivalent to moving the short string to the right to continue matching, but the efficiency of sequential comparison is very low

 KMP uses the effective information of already matched strings to reduce repeated matches.

 For example, in the figure, when the long string and the short string are successfully matched for a certain interval, the matching at positions i and j+1 in the figure fails. According to the conventional thinking, we need to move the short string backward by one position and continue to start the match again. , but kmp is to make good use of the matched information to reduce the number of matches, that is, let j=ne[j], start matching from the position of ne[j], because the part we draw with the black line in the figure is actually equal to It is effective, so we don’t need to match this part, so how to find this ne[j] array?

Here is a concept to introduce, that is, prefix and suffix :

 Now that we know the idea, how to implement it with code?

Ideas:

 code:

	for (int i = 2, j = 0; i <= m; i++)
	{
		while (j && str1[i] != str1[j + 1])j = ne[j];
		if (str1[j + 1] == str1[i])j++;
	    ne[i] = j;
	}

Next, let's simulate a sample:

 topic:

AC code:

#include<iostream>
#include<cstring>
using namespace std;
const int N = 1000010, M = 10010;
char str[N], str1[M];
int ne[N], n, m;

int main(void)
{
	cin >>(str + 1) >>(str1 + 1);
	int n = strlen(str+1), m = strlen(str1+1);
	//获取ne数组
	for (int i = 2, j = 0; i <= m; i++)
	{
		while (j && str1[i] != str1[j + 1])j = ne[j];
		if (str1[j + 1] == str1[i])j++;
		ne[i] = j;
	}
	//开始匹配
	for (int i = 1, j = 0; i <= n; i++)
	{
		while (j && str1[j + 1] != str[i])j = ne[j];
		if (str[i] == str1[j + 1])j++;
		if (j == m)
		{
			printf("%d\n", i - m+1);
		}
	}
	for (int i = 1; i <= m; i++)
	{
		printf("%d ", ne[i]);
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/AkieMo/article/details/128434277