1. 程式人生 > >poj 2752 kmp 前後綴

poj 2752 kmp 前後綴

Seek the Name, Seek the Fame

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 24500 Accepted: 12787

Description

The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the innovative little cat works out an easy but fantastic algorithm: Step1. Connect the father's name and the mother's name, to a new string S. Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S). Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:)

Input

The input contains a number of test cases. Each test case occupies a single line that contains the string S described above. Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000.

Output

For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby's name.

Sample Input

ababcababababcabab
aaaaa

Sample Output

2 4 9 18
1 2 3 4 5

Source

傳送門

題意:要求的找出滿足既是字串的s的字首又是字尾的字串輸出該字串的長度。

先看看next陣列的含義:    1:next陣列只和模式串本身有關和文字串是無關的,因為next表示的是當匹配失敗後模式串要回溯到哪個位置。    2:next陣列儲存的資料是用來當模式串與主串不匹配的時候要模式串回退到第幾個字元與主串再重新匹配,我們知道KMP演算法的主串是不回朔的,當不匹配的時候我們不是退回到開始位置重新匹配,而是利用已經匹配的結果將模式串回朔到下一個位置,這個位置比開始位置更近一步; 簡單的說就是next[ j ]的值儲存的是當模式串中第 j 個字元與主串第 i 個字元不匹配時候,模式串中的哪個字元 重新與主串第 i 個再匹配,這樣總的字元比較次數比從開始位置比較的次數就少了。    3:next[j]儲存的就是模式串前j個字元裡字首和字尾最大的匹配長度;也就是有j = next[j] ; 假設有模式串“abcabx”,那麼next[5] = 2就是前5個字元裡字首和字尾匹配最長的長度為2即“ab”;那麼就是說如果next[len] = ans , 整個串的字首和字尾最長匹配的長度就是ans,上面的字串“abcabx”的最長匹配就是0。    4:在模式串與標準串進行匹配時,指向他們的指標分別為j、i;當p[j]!=s[i]時,j直接變為next[j],新的p[j]繼續與s[i]比較,如果不相等繼續進行此操作……那麼陣列next[j]同樣反映了,在模式串p的第j個位置之前,p[0]~p[next[j]-1]與p[i-next[j]]~p[i-1]這兩段是完全一樣的。假設模式串為“abcdabx”,手動模擬即可知道。

比較長 得耐心看完 會有收穫的

看完是不是還是有些懵 下面舉個栗子

"alala"的字首分別為{"a", "al", "ala", "alal", "alala"},字尾分別為{"a", "la", "ala", "lala", "alala"}.其中有{"a", "ala", "alala"}是相同的,即輸入1,3,5。

a    l   a    l    a

-1  0   0   1   2   3  next陣列的值

因為next表示的是當匹配失敗後模式串要回溯到哪個位置。也是說next陣列回溯到的那個位置之前的字母或數字都是匹配的(..只可意會不可言傳)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
string s;
int nexxt[400010];
int a[400010];
void getnext()
{
	int i=0,j=-1;
	nexxt[0]=-1;
	while(i<s.size())
	{
		if(j==-1||s[i]==s[j])
		{
			nexxt[++i]=++j;
		}
		else
		j=nexxt[j];
	}
	
}
int main()
{
	while(cin>>s)
	{
		int cnt=0;
		getnext();
		int t=nexxt[s.size()-1];
		while(t!=-1)
		{
			if(s[t]==s[s.size()-1])
			a[cnt++]=t+1;
			t=nexxt[t];
		}
		for(int i=cnt-1;i>=0;i--)
		cout<<a[i]<<" ";
		cout<<s.size()<<endl;
	}
	return 0;
}