POJ 2752 Seek the Name, Seek the Fame

http://poj.org/problem?id=2752
这道题目的大意是:给你一个字符串,求他的前缀和后缀相等时的长度例如 字符串alala   :有 a=a ala=ala  alala=alala三种情况。答案是1 3 5  
解题思路KMP的next数组。 就如题目中的例子原串=ababcababababcabab,next=0 1 1 2 3 1 2 3 4 5 4 5 4 5 6 7 8 9 10

我们知道next[19]=10,意思也就是说你当前的字符串与原串在第19个字符不同了,你下一次跳到你要比较的字符串的第10和原串的第19位进行比较,根据next数组的定义,也就是说前缀的9个字符和后缀的9个是一样的所以直接让你的串的第10个和原串的19位相比较而next[10]=5,也就是说你已经比较完了前四个,直接第五个和19位比较,下面的一致类推.....

当然,实际的时候我们访问数组一般默认是从下标0开始到下标strlen(s)-1的,所以会有点差别。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<iomanip>
#include<list>
#include<deque>
#include<map>
#include <stdio.h>
#include <queue>

#define maxn 10000+5
#define ull unsigned long long
#define ll long long
#define reP(i,n) for(i=1;i<=n;i++)
#define rep(i,n) for(i=0;i<n;i++)
#define cle(a) memset(a,0,sizeof(a))
#define mod 90001
#define PI 3.141592657
#define INF 1<<30
const ull inf = 1LL << 61;
const double eps=1e-5;

using namespace std;

bool cmp(int a,int b){
return a>b;
}
char s[400003];
int m;
int f[400003];
void getFail(char *p,int *f)
{

m=strlen(p);
f[0]=0;
f[1]=0;
for(int i=1;i<m;i++)
{
int j=f[i];
while(p[i]!=p[j]&&j)
{
j=f[j];
}
f[i+1]=p[i]==p[j]?j+1:0;
}
// for(int i=1;i<=5;i++)
// cout<<f[i]<<"/"<<endl;
}
///要理解好f[]数组。
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int ans[400000];
while(~scanf("%s",&s))
{
getFail(s,f);
int num=0;
int j=m;
while(j!=0)///精辟经典经典
{
ans[++num]=j;
j=f[j];
}
for(int i=num;i>=1;i--)
{
cout<<ans[i];
if(i!=1)cout<<" ";
else cout<<endl;
}
}
return 0;
}


POJ 2752 Seek the Name, Seek the Fame_第1张图片
 

 



你可能感兴趣的:(POJ 2752 Seek the Name, Seek the Fame)