POJ2752 Seek the Name, Seek the Fame【KMP】

P O J 2752   S e e k   t h e   N a m e , S e e k   t h e   F a m e POJ2752\ Seek\ the\ Name, Seek\ the\ Fame POJ2752 Seek the Name,Seek the Fame
【简要题意】
给定一个字符串,从小到大输出 s s s中既是前缀又是后缀的子串长度
【题解】
K M P KMP KMP比较裸的题,考察对 K M P KMP KMP n x t nxt nxt数组的理解
借用 K M P KMP KMP算法的 n e x t next next数组,设s的长度为 n n n,则 s s s串本身必定满足条件。其他满足条件的子串特征:该子串的最后一个字符肯定与 s s s的最后一个字符相同。这正是 n e x t next next数组发挥作用的时候。从 n − 1 n - 1 n1位既最后一位开始回滚,若 s [ n e x t [ n − 1 ] ] = = s [ n − 1 ] s[next[n-1]] == s[n-1] s[next[n1]]==s[n1],则子串 s [ 0 , 1 , 2 , . . . , n e x t [ n − 1 ] ] s[0,1,2,...,next[n-1]] s[0,1,2,...,next[n1]]是满足条件的子串。然后判断 s [ n e x t [ n e x t [ n − 1 ] ] ] = = s [ n − 1 ] s[next[next[n-1]]] == s[n-1] s[next[next[n1]]]==s[n1]是否成立,这样一直回滚,直到 n e x t [ n e x t [ . . . . . n e x t [ n − 1 ] ] ] = = 0 next[next[.....next[n-1]]] == 0 next[next[.....next[n1]]]==0(即已经匹配到第一位)为止。把答案从大到小存下来,再从小到大输出即可。
多组数据注意清空

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
const int N=400000+50;
int kmp[N],j,ans[N];
char b[N];
inline int read(){
	int cnt=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
	while(isdigit(c)){cnt=(cnt<<1)+(cnt<<3)+(c^48);c=getchar();}
	return cnt*f;
}
signed main(){
	while (scanf("%s", b+1)!=EOF){
		memset(kmp,0,sizeof(kmp));
		j=0;
		int lb=strlen(b+1);
		for (int i=2;i<=lb;i++){     
		   	while(j&&b[i]!=b[j+1])
	    		j=kmp[j];    
	      	if(b[j+1]==b[i])j++;    
	        kmp[i]=j;
	    }
	    int cnt=0;
	    int t=kmp[lb];
	    while(t!=0){
	    	if(b[t]==b[lb])ans[++cnt]=t;
			t=kmp[t];
	    }	
	    for(int i=cnt;i>=1;--i){printf("%d ",ans[i]);}
		printf("%d\n",lb);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值