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这种意义不明的东西,一定会成为黑历史的……

猜你喜欢

转载自blog.csdn.net/guluugulu/article/details/18924217
今日推荐