1. 程式人生 > >POJ 2752 Seek the Name, Seek the Fame(KMP的next陣列)

POJ 2752 Seek the Name, Seek the Fame(KMP的next陣列)

【連結】http://poj.org/problem?id=2752

【題意】給個字串,求這個串所有字首與字尾相同的所有綴長度

【思路】

其實kmp裡的next這個微妙的陣列本身就是答案了,至於為什麼,我是用以前不知道哪裡弄來的的kmp模板試了一下看出來的【喂

從next陣列的最後一個值起往前找,只要next[i]的值不是-1,就說明s[0]~s[i]這個串有滿足本題條件的綴,綴的長度為next[i]+1(下標從0),記錄這個綴

下一步i=next[i],即從綴裡找綴,將原來的綴作為字串,按上面的步驟繼續找,直到next[i] == 0

……樣例君它是這樣的:


① ababcababababcabab(整個字串),next[17]=8,說明長度9是一個答案,即綴1=字首=字尾=ababcabab

② ababcabab(①中的綴),next[8]=3,說明長度4是一個答案,即綴2=字首=字尾=abab

③ abab,next[3]=1,說明長度2是一個答案,即綴3=字首=字尾=ab

④ ab,next[1]=-1,找不出綴了,停~

⑤ 加上原來的字串一整個作為字首也作為字尾的答案,所有的就是了

 

【程式碼】……本想把printArray這種羞澀的巨集去掉的不過好吧好吧既然用上了就放著吧……

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <map>
#include <vector>
#include <set> 
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;

#define MAX_LEN 400005
#define ll long long 
#define mod 100000007

#define MEM(a,al) memset(a,al,sizeof(a))
#define sfx(x) scanf("%lf",&x)
#define sfxy(x,y) scanf("%lf%lf",&x,&y)
#define sdx(x) scanf("%d",&x)
#define sdxy(x,y) scanf("%d%d",&x,&y)
#define pfx(x) printf("%.0f\n",x)
#define pfxy(x,y) printf("%.6f %.6f\n",x,y)
#define pdx(x) printf("%d\n",x)
#define pdxy(x,y) printf("%d %d\n",x,y)
#define getArray(a,len) for(int ia = 0; ia < len; ia++) scanf("%d",&a[ia])
#define printArray(a,len) for(int ia = 0; ia < len; ia++) printf("%d%c",a[ia],(ia==len-1)?'\n':' ')
#define fora(i,n) for(i = 0; i < n; i++)
#define fora1(i,n) for(i = 1; i <= n; i++)
#define foraf(i,n) for(int i = 0; i < n; i++)
#define foraf1(i,n) for(int i = 1; i <= n; i++)
#define ford(i,n) for(i = n-1; i >= 0; i--)
#define ford1(i,n) for(i = n; i > 0; i--)
#define fordf(i,n) for(int i = n-1; i >= 0; i--)
#define fordf1(i,n) for(int i = n; i > 0; i--)

class WriteInfo{
public:
	void info() { printf("[Info] "); }
	void infoEnd() { printf(" [/Info]\n"); }
} W;

const int INF = 1<<29;
const double INFD = 1e20;
const double eps =  1e-6;

int n,m,len;
char s[MAX_LEN];
int next[MAX_LEN];
int res[MAX_LEN];

void getNext(){
	MEM(next,-1);
	int j = -1;
	foraf1(i, len-1){
		while(j > -1 && s[i] != s[j+1]) j = next[j];
		if (s[i] == s[j+1]) j++;
		next[i] = j;
	}
}

int main() {
	int i,j,k;
	int T; 
	
	while(scanf("%s",s) != EOF){
		len = strlen(s);
		getNext();
		i = len-1;
		j = 0;
		while(next[i] != -1){
			res[j++] = next[i]+1;
			i = next[i];
		}
		// 本身也符合字首等於字尾,都是自己 
		res[j++] = len;
		sort(res,res+j);
		printArray(res,j);
	}

	return 0;
}

 第一篇部落格就是kmp這種意義不明的東西,一定會成為黑歷史的……