POJ2752 Seek the Name, Seek the Fame 【既是前缀又是后缀的子串】


【题目大意】

输入一个仅含小写字母的字符串,求出其子串的长度,该子串满足条件:既是前缀又是后缀。输入包含多组数据。

【解题思路】

分析题意,得知该题是求给定字符串的所有前缀后缀子串的长度。(以下将前缀后缀串简称为PS串(Prefix-Suffix))

显然,设B为A的PS串,则有A[i]=A[len-1](下标从零开始),其中A[i]为B的最后一位。

所以可以利用KMP优越的匹配性能直接从头开始匹配,如果某一位存在上述性质则存下来,最后倒序输出。

【代码】:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<cctype>
#include<iomanip>
//#define LOCAL
using namespace std;

const int N=400011;
int F[N];
char T[N];
int ans[N];

void Fail(char *T,int *F){
	F[0]=-1;
	int posm=strlen(T);
	for (int i=1;i<posm;++i){
		int j=F[i];
		while (j&&T[i]!=T[j]) j=F[j];
		F[i+1]=(T[i]==T[j]) ? j+1 : 0;
	}
}

int main(){
#ifdef LOCAL
    freopen("POJ2752.in","r",stdin);
#endif
    while (scanf("%s",T)!=EOF){
    	Fail(T,F);
    	int len=strlen(T);
    	int zjl=F[len-1];
    	int cnt=0;
    	while (zjl!=-1){
    	    if (T[zjl]==T[len-1]) ans[cnt++]=zjl+1;
    	    zjl=F[zjl];
	}
	for (int i=cnt-1;i>=0;--i) printf("%d ",ans[i]);
	printf("%d\n",len);
    }
    return 0;
}


【总结】

PS串的解决方法——直接KMP+性质判定。

展开阅读全文

没有更多推荐了,返回首页