poj 2752 kmp 前后缀

Seek the Name, Seek the Fame

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 24500 Accepted: 12787

Description

The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the innovative little cat works out an easy but fantastic algorithm:

Step1. Connect the father's name and the mother's name, to a new string S.
Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S).

Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:)

Input

The input contains a number of test cases. Each test case occupies a single line that contains the string S described above.

Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000.

Output

For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby's name.

Sample Input

ababcababababcabab
aaaaa

Sample Output

2 4 9 18
1 2 3 4 5

Source

POJ Monthly--2006.01.22,Zeyuan Zhu

传送门

题意:要求的找出满足既是字符串的s的前缀又是后缀的字串输出该字串的长度。

先看看next数组的含义:
   1:next数组只和模式串本身有关和文本串是无关的,因为next表示的是当匹配失败后模式串要回溯到哪个位置。
   2:next数组存储的数据是用来当模式串与主串不匹配的时候要模式串回退到第几个字符与主串再重新匹配,我们知道KMP算法的主串是不回朔的,当不匹配的时候我们不是退回到开始位置重新匹配,而是利用已经匹配的结果将模式串回朔到下一个位置,这个位置比开始位置更近一步;
简单的说就是next[ j ]的值保存的是当模式串中第 j 个字符与主串第 i 个字符不匹配时候,模式串中的哪个字符 重新与主串第 i 个再匹配,这样总的字符比较次数比从开始位置比较的次数就少了。
   3:next[j]存储的就是模式串前j个字符里前缀和后缀最大的匹配长度;也就是有j = next[j] ; 假设有模式串“abcabx”,那么next[5] = 2就是前5个字符里前缀和后缀匹配最长的长度为2即“ab”;那么就是说如果next[len] = ans , 整个串的前缀和后缀最长匹配的长度就是ans,上面的字符串“abcabx”的最长匹配就是0。
   4:在模式串与标准串进行匹配时,指向他们的指针分别为j、i;当p[j]!=s[i]时,j直接变为next[j],新的p[j]继续与s[i]比较,如果不相等继续进行此操作……那么数组next[j]同样反映了,在模式串p的第j个位置之前,p[0]~p[next[j]-1]与p[i-next[j]]~p[i-1]这两段是完全一样的。假设模式串为“abcdabx”,手动模拟即可知道。

比较长 得耐心看完 会有收获的

看完是不是还是有些懵 下面举个栗子

"alala"的前缀分别为{"a", "al", "ala", "alal", "alala"},后缀分别为{"a", "la", "ala", "lala", "alala"}.其中有{"a", "ala", "alala"}是相同的,即输入1,3,5。

a    l   a    l    a

-1  0   0   1   2   3  next数组的值

因为next表示的是当匹配失败后模式串要回溯到哪个位置。也是说next数组回溯到的那个位置之前的字母或数字都是匹配的(..只可意会不可言传)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
string s;
int nexxt[400010];
int a[400010];
void getnext()
{
	int i=0,j=-1;
	nexxt[0]=-1;
	while(i<s.size())
	{
		if(j==-1||s[i]==s[j])
		{
			nexxt[++i]=++j;
		}
		else
		j=nexxt[j];
	}
	
}
int main()
{
	while(cin>>s)
	{
		int cnt=0;
		getnext();
		int t=nexxt[s.size()-1];
		while(t!=-1)
		{
			if(s[t]==s[s.size()-1])
			a[cnt++]=t+1;
			t=nexxt[t];
		}
		for(int i=cnt-1;i>=0;i--)
		cout<<a[i]<<" ";
		cout<<s.size()<<endl;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值