题目链接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;