Match:Cyclic Nacklace(kmp的next数组的高级应用)(HDU 3746)

                 

                  串珠子

  题目大意:给定一个字串,要你找到如果要使之成为循环串,在末尾需要的最小的字数(只能添加字符,不能删减字符)

  首先联动一下之前做过的动态规划问题POJ 3280,当然了3280这一题是用的LD,因为他可以添加或者删除(加上修改也行,但是要改状态方程了)

  而我们现在要讨论的这一题(HDU 3746)是有限制的,首先它只能添加不能删除,其次一定是要在末尾添加。

  其实这样的题用kmp可以很快地解决,其实这样的题目是循环节的题目,之前我已经写过很多了,这一题是对循环节的深刻理解。

  首先我们我们明白,对于kmp算法的next数组,如果一个字串是循环字串,那么他一定有len%(len-next[len])==0且next[len]>0,这个已经从1961等题论证了

  现在我们就是要搞清楚,如果len%(len-next[len])!=0会如何,我们先来看一个例子

  

  比如上个例子,他的最大前缀和后缀是abcdeabcd,如果要在末尾加上字符使他循环,那么一定是要加上e,使新的循环节是abcde,而abcde的长度刚好是len-next[len]

  

  再如这个例子,最大前缀和后缀是abcabcab,末尾加上c循环节就是abc,刚好也是len-next[len]

  

  对于这个,不存在最大前后缀,必须加上len才能使之成为循环字串,而next[len]刚好是0,也符合len-next[len]

  那么我们是不是能下结论,无论对于什么字串,无论是否循环,最小的循环节一定是len-next[len]呢?答案是最小循环节一定满足这个结论

  我们再来看第二组

  我们把最大前后缀对齐,发现突出的部分的长度就是新的数组的循环节的长度,事实上,我们将任何数组按照这个方式对齐都有这个结论,就是突出的长度刚好是新的数组的循环节的长度,而这个长度刚好就是len-next[len](非严格证明),那么原数组按照新的循环节划分会剩下len%(len-next[len])个单元(注意len-next[len]要特判,因为可能会存在len-next[len]==0),接着我们就可以直接用len-len%(len-next[len])得到需要补齐的长度了,这就是循环节题目的一般做法。  

  参考:http://blog.csdn.net/u013480600/article/details/22954037

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <functional>
 4 #include <string.h>
 5
 6 using namespace std;
 7
 8 static char input[100010];
 9 static int _Next[100010];
10
11 void Get_Next(const int);
12
13 int main(void)
14 {
15     int case_sum, len;
16     scanf("%d", &case_sum);
17
18     while (case_sum--)
19     {
20         scanf("%s", input);
21         len = strlen(input);
22         Get_Next(len);
23
24         if (_Next[len] == 0)//不存在循环节
25             printf("%d\n", len);
26         else if (len % (len - _Next[len]) == 0)//已经是循环节了
27             printf("0\n");
28         else
29             printf("%d\n", len - _Next[len] - len % (len - _Next[len]));
30     }
31     return EXIT_SUCCESS;
32 }
33
34 void Get_Next(const int len)
35 {
36     int i = 0, k = -1;
37     _Next[0] = -1;
38
39     while (i < len)
40     {
41         if (k == -1 || input[i] == input[k])
42         {
43             i++;
44             k++;
45             _Next[i] = k;
46         }
47         else k = _Next[k];
48     }
49 }

  

时间: 2024-10-19 08:46:20

Match:Cyclic Nacklace(kmp的next数组的高级应用)(HDU 3746)的相关文章

hdu 3746 Cyclic Nacklace (KMP求最小循环节)

//len-next[len]为最小循环节的长度 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int len; char a[100010]; int next[100010]; void Getnext() { int i=0,j=-1; next[0]=-1; while(i<=len) { if(j==-1||a[i]==a[j]) i

HDU 3746 Cyclic Nacklace (KMP 循环节)

分析:对next数组的深入理解,最重要的还是对最小循环节的处理. #include <stdio.h> #include <string.h> int next[100005]; char str2[100005]; void build_next(int len2) { int i=0,j=-1; next[0] = -1; while (i < len2) { if (j==-1 || str2[i] == str2[j]) { i++; j++; // if (str2

hdu 3746 Cyclic Nacklace KMP循环节问题

Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4124    Accepted Submission(s): 1866 Problem Description CC always becomes very depressed at the end of this month, he has checke

HDU 3746 Cyclic Nacklace (KMP找循环节)

题目链接:HDU 3746 Sample Input 3 aaa abca abcde Sample Output 0 2 5 Author possessor WC Source HDU 3rd "Vegetable-Birds Cup" Programming Open Contest Solution 题意 给定一个字符串,问至少需要在末尾添加多少个字符使得字符串循环. 思路 KMP 设前缀函数为 \(\pi()\),字符串长度为 \(n\),下标从 \(1\) 开始. 最小循环

hdu 3746 Cyclic Nacklace KMP

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3746 题目: Problem Description CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, without any surprise, there are only 99.9 yuan left. he is too distressed

HDU 3746 Cyclic Nacklace (KMP找循环节)

Problem Description CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, without any surprise, there are only 99.9 yuan left. he is too distressed and thinking about how to tide over the last days. Bein

HDU_3746 Cyclic Nacklace(KMP)

题目请点我 题解: 题目大意:有一个字符串s,可以在前后添加字符,使字符串成为一个循环次数至少为2的循环字符串,输出最少需要添加的字符数目. 首先可以证明题目可以等价为只在末尾添加字符使满足题意,要找到添加资格字符我们首先要找到循环单位的长度,利用一个辅助数组储存从起始位置开始长度为i的串的循环长度,初始值为i,利用与Next数组之间的关系来更新,找到循环长度,比如字符串abcabc,Next[i] = 3,cycle[3] = 3,有等价关系i-Next[i] = cycle[Next[i]]

HDU3746 Cyclic Nacklace KMP求循环节

HDU3746给定一个字符串,求:在该字符串末尾最少补充多少个字符,可以使得这个字符串获得周期性. 周期性指存在一个子串,使得该字符串可以正好分解成若干个这个子串(数量要大于1). Input 第一行是一个整数 T ( 0<T<=100 ) 代表测试数据的组数. 之后T行每行一个字符串,由小写字母组成,字符串的长度3<=L<=100000. Output 每组数据输出一行结果. Sample Input 3 AAA ABCA ABCDE Sample Output 0 2 5 本题

(KMP 1.4)hdu 3746 Cyclic Nacklace(使用next数组来求循环节的长度——求一个字符串需要添加多少个字符才能使该字符串的循环节的个数&gt;=2)

题目: Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3387    Accepted Submission(s): 1549 Problem Description CC always becomes very depressed at the end of this month, he has che