题意:
给一个串s,求他所有的前缀和后缀相等的时候的子串长度,按从小到大输出
题解:
刚开始我也知道是next数组的运用,但是想了半天也没发现有什么练习,想模拟一遍找规律,但是失败了,无奈上网搜解题报告,发现都是next数组回溯就可以了,自己试了一下发现果真是这样= =,但是心中一万个不懂啊!!网上的题解一个比一个简单,解释也一笔带过,不过后来查到一个文档上面有图,虽然也是两三行就说完了,但是看着图才发现其中的奥妙。
先说规律,就好比他给的例子:
ababcababababcabab
一共18位,next数组内容是:-1,0,0,1,2,0,1,2,3,4,3,4,3,4,5,6,7,8,9
next[n]=9;next[9]=4;next[4]=2;next[2]=0;
逆序输出,0舍掉,再加一个最后全部的18(因为整个串为前缀的话,整个串也为后缀,两者必相等)
就是2,4,9,18为正确答案了
下面解释为什么会是这种规律
看上图,next[18]=9,说明图中红色和绿色完全相同,此时第二大的前缀跟后缀相等即为next[n]=9;(第一大是母串本身18)
再到下一图,next[9]=4,表示前9格中,前4个(深蓝)和后四个(天蓝)相同,而前9个和后9个又相同,可推出前4个和后4个相同(两个深蓝一样)
再到下一图,next[4]=2,表示前4格中,前两个(黄色)和后两个(黄色)相同,而对于母串而言,前4个和后四个两个深蓝相同,可得前两个和后两个相同(两个黄色一样)
而next[2]=0,表示前2格中没有相同的前缀和后缀了,所以循环终止
这样通过next[]数组本身的含义我们推出了以上公式
题目:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 9653 | Accepted: 4631 |
Description
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
Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000.
Output
Sample Input
ababcababababcabab aaaaa
Sample Output
2 4 9 18 1 2 3 4 5
Run ID | User | Problem | Result | Memory | Time | Language | Code Length | Submit Time |
11775626 | chengtbf | 2752 | Accepted | 2632K | 141MS | C++ | 731B | 2013-07-13 14:29:55 |
代码:
#include<stdio.h>
#include<string.h>
#define N 400005
int ans[N];
char str[N];
int next[N];
int n;
void get_next()
{
int pos=2;
int cnd=0;
next[0]=-1;next[1]=0;
while (pos<=n)
{
if (str[pos-1]==str[cnd])
{
cnd++;
next[pos]=cnd;
pos++;
}
else if(cnd>0)
{
cnd=next[cnd];
}
else
{
next[pos]=0;
pos++;
}
}
}
int main()
{
int i,j,k;
while (scanf("%s",str)!=EOF)
{
n=strlen(str);
get_next();
i=n;j=1;
while (1)
{
if (next[i]<=0)
{
break;
}
else
{
ans[j]=next[i];
j++;
i=next[i];
}
}
for ( k = j-1; k >=1 ; k--)
{
printf("%d ",ans[k]);
}
printf("%d\n",n);
}
return 0;
}