码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3746 - Cyclic Nacklace(KMP)

时间:2016-03-19 00:54:34      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

  http://acm.hdu.edu.cn/showproblem.php?pid=3746

题目描述:

  给定一个字符串S,问至少需要添加多少个字符,使得新字符串拥有两个以上的循环节。

解题思路:

  又一个next数组的应用(由于next数组在C++内不能使用,所以我使用失配数组也即fail数组,其实两个数组都是一样的)。计算得出next数组后,由于题目要求在原字符串右边添加字符,所以直接看最后一个字符的next值,最后一个字符的next值可以分两种情况:

  1.next = 0.这种情况表示字符串中不存在公共前后缀,那么要得到两个循环节就只能再添加一段原字符串了。

  2.next > 0.这种情况表明我们只需要在字符串后添加原字符串的子串就可以得到合法的字符串了,那么问题来了,这个子串究竟是多长呢?已知该next值就是字符串最长公共前后缀长度,那么去掉后缀的那一部分字符串就是循环节啦。因为如果那部分字符串不是循环节,那么就没有公共前后缀啦。所以知道了循环节的长度,就只需要与原字符串长度进行比较就可以知道要添加多少字符啦。

代码:

 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <vector>
 6 #include <algorithm>
 7 using namespace std;
 8 
 9 #define ll long long
10 #define INF 0x3f3f3f3f3f
11 #define MAX 100100
12 
13 char T[MAX];
14 int fail[MAX];
15 
16 void getFail()
17 {
18     fail[0] = 0;
19     int k = 0;
20     int len = strlen(T);
21     for(int i = 1; i < len; ++i) {
22         while(k > 0 && T[i] != T[k])
23             k = fail[k - 1];
24         if(T[i] == T[k])
25             k++;
26         fail[i] = k;
27     }
28 }
29 
30 int main()
31 {
32     //freopen("debug\\in.txt", "r", stdin);
33     //freopen("CON", "w", stdout);
34     int i, j, k;
35     int test;
36     scanf("%d", &test);
37     while(test--) {
38         scanf("%s", T);
39         //memset(fail, 0, sizeof(fail));
40         int len = strlen(T);
41         getFail();
42         if(fail[len-1] == 0) {
43             printf("%d\n", len);
44             continue;
45         }
46         int t = len - fail[len-1];
47         if(len % t == 0)
48             printf("0\n");
49         else
50             printf("%d\n", t - len % t);
51     }
52     return 0;
53 }

 

HDU 3746 - Cyclic Nacklace(KMP)

标签:

原文地址:http://www.cnblogs.com/lc520love/p/5294152.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!