HDU-3736 Cyclic Nacklace KMP
Cyclic Nacklace
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 264 Accepted Submission(s): 127
As Christmas is around the corner, Boys are busy in choosing christmas presents to send to their girlfriends. It is believed that chain bracelet is a good choice. However, Things are not always so simple, as is known to everyone, girl's fond of the colorful decoration to make bracelet appears vivid and lively, meanwhile they want to display their mature side as college students. after CC understands the girls demands, he intends to sell the chain bracelet called CharmBracelet. The CharmBracelet is made up with colorful pearls to show girls' lively, and the most important thing is that it must be connected by a cyclic chain which means the color of pearls are cyclic connected from the left to right. And the cyclic count must be more than one. If you connect the leftmost pearl and the rightmost pearl of such chain, you can make a CharmBracelet. Just like the pictrue below, this CharmBracelet's cycle is 9 and its cyclic count is 2:
Now CC has brought in some ordinary bracelet chains, he wants to buy minimum number of pearls to make CharmBracelets so that he can save more money. but when remaking the bracelet, he can only add color pearls to the left end and right end of the chain, that is to say, adding to the middle is forbidden.
CC is satisfied with his ideas and ask you for help.
Each test case contains only one line describe the original ordinary chain to be remade. Each character in the string stands for one pearl and there are 26 kinds of pearls being described by 'a' ~'z' characters. The length of the string Len: ( 3 <= Len <= 100000 ).
该题旨在要求我们计算出达到两个循环节所补充的最少字符数,例如样例中的 "aaa" 已经满足达到两个循环,实质上已经有三个循环;"abca" 只需再补上 "ab" 两个字符即满足题意,而 "abcde" 则必须补上 5个字符才能满足题意了。
这道题也是想了不少时间,原因在于我一直希望在求 next[] 数组时将其求解出来,当时的想法是假定母串无限长,超过原字符串长度就当做是任意字符进行处理,即无条件进行匹配,我觉得前面的思想还是不错的,但是后面的想法就有点天真了,由于是错误的答案就不在这里罗嗦了。
后面发觉其实假设它为任意字符,不就是填充吗?找到循环节不就行了吗? 于是本题的关键就在寻找出循环节了,如何去找呢?这里还是要借助 next[] 的值,其实给定的一个串的循环节完全取决于最后一个字符后面假设字符的next[] 值(因为它反映了最后一个字符的匹配情况),为什么这么说呢,因为当我们考察最后一个字符的匹配情况时,我们就知道了最后这个字符能匹配够到该串的具体位置,而我们再用全串的长度减去这部分匹配的长度然后加上一,得到的就是循环节的长度了。
代码如下:
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> char str[100005]; int next[200010], flag; void getnext( char *s, int *next ) { int k= 1, j= 0, len= strlen( s+ 1 ); next[k]= 0; while( k<= len ) { if( j== 0|| s[k]== s[j] ) { ++j, ++k; if( s[k]= s[j] ) { next[k]= next[j]; } next[k]= j; } else { j= next[j]; } } } int main() { int T; scanf( "%d", &T ); while( T-- ) { scanf( "%s", str+ 1 ); getnext( str, next ); int len= strlen( str+ 1 ); flag= len- next[len+ 1]+ 1; printf( len > flag && len% flag== 0? "0\n": "%d\n", flag- len% flag ); } return 0; }