D - 娜娜梦游仙境系列——村民的怪癖
Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
Submit Status
Problem Description
娜娜费劲九牛二虎之力终于把糖果吃完了(说好的吃不完呢?骗人,口亨~),于是,缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷,娜娜甚异之。复前行,欲穷其林。林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田美池桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。(摘自《桃花源记》)
娜娜与村民交流了好久才发现这里的人们给孩子的命名方式很奇怪,首先村民们的名字都是用专门的符号来记录,正好是26个符号,于是娜娜就把它们替换成‘a’~‘z’,然后首先把爸爸的名字作为孩子的姓,妈妈的名字作为孩子的名。这时候肯定有人会问,不是独生子女怎么办?很简单~取拼接好的名字的前缀与后缀相同的部分从短到长依次作为孩子的姓名,啥,不够?那就不许你再生孩子!
不过由于桃花村民与世隔绝太久了,以致于他们总是无法正确判断一对夫妻最多能生多少个孩子,于是就把这个任务交给你了。
P.S. 若用S[1,n]表示一个长度为n的字符串,那么S[1,i](1<=i<=n)表示S的一个前缀,S[j,n](1<=j<=n)表示S的一个后缀。具体看样例解释
Input
多组数据,首先是一个正整数t(t<=20),表示数据的组数
对于每一组数据,包含两个只由‘a‘~‘z‘组成的不含空格的字符串S1,S2,分别代表丈夫的姓名以及妻子的姓名。(1<=|S1|,|S2|<=100000)
Output
对于每组数据,输出一个整数,表示这对夫妻最多可以生育多少个孩子。
Sample Input
2 ababc ababa aaaaa aaa
Sample Output
3 8
Hint
对于样例1,把丈夫和妻子的姓名拼接在一起是ababcababa,可以作为孩子的姓名的是a、aba、ababcababa,故最多生育3个孩子
对于样例2,把丈夫和妻子的姓名拼接在一起是aaaaaaaa,可以作为孩子的姓名的是a、aa、aaa、aaaa、aaaaa、aaaaaa、aaaaaaa、aaaaaaaa,故最多生育8个孩子
题解:这一题目在于求,对于新组成的字符串,有多少个相同的以str[0]为起点的前缀和以str[N-1]为终点的后缀,方法在于对Next数组的应用,因为next数组里面存的数是next[i]是表示以str[0]为起点的前缀和以str[i-1]为终点后缀,相同前后缀的最大长度。依照题意,只需要从next[N]=K开始查找下一个next[k],从最大长度的相同前后缀开始查找,找到Next[j]==-1,(查找到第一个字符)直到查找需要多少次查找才能够跳转到第一个字符,输出这个次数就是所要求的答案、
1 #include <iostream> 2 #include <stdio.h> 3 #include<string.h> 4 using namespace std; 5 char STR[300000]; 6 char STR_S[300000]; 7 void getNext(char p[],int next[],int Len_t) /*next数组, */ 8 { 9 int i=0,j=-1; 10 next[0]=-1; /*起点赋值为-1*/ 11 while(i<Len_t) 12 { 13 if(j==-1||p[i]==p[j])next[++i]=++j; 14 else j=next[j]; 15 } 16 } 17 int main() 18 { 19 int next[200005]; 20 int T,i,Len,sum,j,sign; 21 char str; 22 scanf("%d",&T);getchar(); 23 while(T--) 24 { 25 for(i=0;;i++) 26 { 27 str=getchar(); 28 if(str==32)i--; 29 else if(str==‘\n‘){STR[i]=‘\0‘;Len=i;break;} 30 else STR[i]=str; 31 } 32 sum=0; 33 j=Len; 34 getNext(STR,next,Len); /*对合成的串求next数组*/ 35 while(next[j]!=-1) 36 { 37 j=next[j]; /*详细请看next[i]数组的原理,*next[i]里面存的到该i位置相同前后缀的最大长度,*/ 38 sum++; /*以此递归找next中的数,判断需要几次才会跳到起点,来找出会有多少个相同的前后缀*/ 39 } 40 printf("%d\n",sum); 41 } 42 return 0; 43 }