HDU 3746(KMP)

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

题意:给你一个字符串,要求将字符串的全部字符最少循环2次需要添加的字符数。 例子: abcabc 已经循环2次,添加数为0 abcac 没有循环2次,添加字符abcac。数目为5. abcabcab 已

经循环过2次,但第三次不完整,需要添加数为1 分析:还是用到了next数组,这个循环节这很巧妙啊。。。 做这个题需要好好理解KMP算法,尤其是next数组。

非优化的next数组的含义是:next[i]=k默示模式串下标为i的字符的前k-1个字符与开首的前k-1个字符相等,那么从1到i-1的模式串必定是轮回的,且循环节的长度为i-next[i].

理解了这一点这个题就很简单了。

总之 next含义是:

next[j]表代表j之前的字符串的真前缀和真后缀最大匹配长度 next[i]代表了前缀和后缀的最大匹配的值(需要彻底明白这点http://www.shengxun8.com/,相当重要)

非优化的next数组的含义是:next[i]=k默示模式串下标为i的字符的前k-1个字符与开首的前k-1个字符相等

代码如下:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 const int N = 100002;
 6 char str[N];
 7 int  next[N];
 8 
 9 void get_next(int len)
10 {
11         int i = 0;
12         int j = -1;
13         next[i] = -1;
14         while(i < len)
15         {
16             if(j == -1 || str[i] == str[j])
17             {
18                 i++;
19                 j++;
20                 next[i] = j;
21             }
22             else
23             {
24                 j = next[j];
25             }
26         }
27 }
28 
29 int main()
30 {
31     int t;
32     scanf("%d", &t);
33     while(t--)
34     {
35         scanf("%s", str);
36         int len = strlen(str);
37         get_next(len);
38         int x = len - next[len];
39         if(len != x && (len % x == 0))
40         {
41             printf("0\n");
42         }
43         else
44         {
45             printf("%d\n", x - next[len] % x);
46         }
47     }
48     return 0;
49 }

 

参考别人的代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 const int N = 100002;
 6 char str[N];
 7 int next[N];
 8 
 9 void get_next(int len)
10 {
11     int i;
12     int j = 0;
13     for(next[1] = 0, i = 2; i <= len; i++)
14     {
15         while(j && str[j + 1] != str[i])
16         {
17             j = next[j];
18         }
19         if(str[j + 1] == str[i])
20         {
21             j++;
22         }
23         next[i] = j;
24     }
25 }
26 
27 int main()
28 {
29     int t;
30     scanf("%d", &t);
31     while(t--)
32     {
33         scanf("%s", str + 1);
34         int len = strlen(str + 1);
35         get_next(len);
36         int x = len - next[len];
37         if(len % x == 0 && len != x)
38         {
39             printf("0\n");
40         }
41         else
42         {
43             printf("%d\n", x - next[len] % x);
44         }
45     }
46 }

主要是next数组的求法不同,第一种是经过优化的,而第二种未经过优化。

posted @ 2012-08-21 12:04  山路水桥  阅读(342)  评论(0编辑  收藏  举报