1. 程式人生 > >KMP演算法例題+總結

KMP演算法例題+總結

KMP之前沒學,然後排位賽又有一道題考了這個知識點,這題AC了一列人,就差我一個......

KMP演算法:建立一個next函式,從而使字串匹配的時間複雜度由O(n*n)變成O(n+m)。

舉個例子:

ababcab 和 abbbcabdc

首先建立next陣列,next[0] = -1

   ababcab

-10012012就是next陣列了

很簡單吧.....emmmmmmm,其實我也不太會講,有點麻煩,不懂得去B站翻翻視訊看看

例題:

字串什麼的,最喜歡了

Time Limit: 2000/1000ms (Java/Others)

Problem Description:

對於一個字串,可以在後面新增字元,怎麼新增最少的字元使得這個字串變成由一個至少兩遍字首迴圈而成.

Input:

第一行輸入一個T。總共T組資料
第二行輸入一個字串,( 3 <= 長度 <= 100000 ).

Output:

最少的新增的字元個數,每個輸出佔一行。

提示:
qweqwe 剛好兩遍迴圈,所以新增0
qweqe 沒有兩遍,所以新增為5,字元為qweqe 。.
ababa 有兩遍迴圈,但是第三次不完整,所以新增數為1.

Sample Input:

3
aaa
abca
abcde

Sample Output:

0
2
5

AC的標程程式碼(帶解析):

// 1 題目要求的是給定一個字串,問我們還需要新增幾個字元可以構成一個由n個迴圈節組成的字串。
// 2 可知我們應該先求出字串的最小迴圈節的長度:假設字串的長度為len,那麼最小的迴圈節就是cir = len-next[len] ; 如果有len%cir == 0,那麼這個字串就是已經是完美的字串,不用新增任何字元;如果不是完美的那麼需要新增的字元數就是cir - (len-(len/cir)*cir)),相當與需要在最後一個迴圈節上面新增幾個。
// 3 如果cir = 1,說明字串只有一種字元例如“aaa” ; 如果cir = m說明最小的迴圈節長度為m,那麼至少還需m個;如果m%cir == 0,說明已經不用添加了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 100010

char s[N];
int nextval[N];
int len;

void getnext(const char *s)
{
	int i = 0, j = -1;
	nextval[0] = -1;
	while(i != len)
	{
		if(j == -1 || s[i] == s[j])
			nextval[++i] = ++j;
		else
			j = nextval[j];
	}
}

int main()
{
	int ncase;
	int length, add;
	scanf("%d", &ncase);
	while(ncase--)
	{
		scanf("%s", s);
		len = strlen(s);
		getnext(s);
/*		for(int i = 0; i <= len; ++i) //檢視next陣列的內容
			cout<<nextval[i]<<" ";
		cout<<endl;
		length = len - nextval[len]; //迴圈節的長度
		cout << length <<endl;*/
		if(len != length && len % length == 0) //迴圈多次
			printf("0\n");
		else
		{
			add = length - nextval[len] % length; //取餘的作用:abcab,去掉abc
			printf("%d\n",add);
		}
	}
	return 0;
}

附上個部落格:http://www.cnblogs.com/jackge/archive/2013/01/05/2846006.html  我就是看這個部落格懂的這題