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数组的求法不同,第一种是经过优化的,而第二种未经过优化。

你可能感兴趣的:(HDU)