hdu 3746 Cyclic Nacklace

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=3746

题意就是给出一个字符串,让你可以在左边或者右边添加一定数量(输出最小数量)的字符使其可以成为一个有循环的最小长度的圆,

不可以从中间插入字符,因为最终是要连接成一个圆,所以无论从左边还是右边添加最后效果都是一样的,下面考虑从右面开始添加

这题主要是对KMP中next数组的应用,另外还有循环节的小技巧

假设字符串长度为len,那么求出next[len]即为该串后缀与前缀的最大匹配数,那么需要构成最小长度圆的循环节长cir=len-next[len];

所以说当len%cir==0 && len!=cir是表示该串无需要添加任何字符则可以构成符合条件的圆环

反之则需要添加一定数量的字符,添加最少数量为cir-(next[len]%cir)

这题很不理解用算法导论上那种求next数组的方法为什么会超时,AC的代码是采用的网上找来的球next数组的方法,用着也很不错

代码如下

View Code
 1 # include <stdio.h>
 2 # include <string.h>
 3 int next[100010];
 4 int len;
 5 int COUNT_next(char *str)
 6 {
 7    int i=0,j=-1;
 8    next[0]=-1;
 9    while(i<len)
10    {
11        if( j==-1 || str[i] == str[j] )
12         {
13             ++i;
14             ++j;
15             next[i] = j;
16         }//每当自增i和j,得到一个新的next[i]
17         else j = next[j];//模式串向右移动
18    }
19 
20 }
21 int main()
22 {
23     int n, cir;
24     char str[100010];
25     scanf("%d",&n);
26     while(n--)
27     {
28         scanf("%s", str);
29         len = strlen(str);
30         memset(next,0,sizeof(next));
31         COUNT_next(str);
32         cir=len - next[len];
33         //printf("%d~\n",next[len]);
34         if(len%cir==0 && len != cir) printf("0\n");
35 
36         else printf("%d\n",cir-(next[len]%cir));
37     }
38     return 0;

 

posted @ 2013-04-18 18:01  一缕阳光~~  阅读(148)  评论(0编辑  收藏  举报