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

  • 相关阅读:
    产品经理必备工具之一:Axure产品原型设计
    解决UserDefault读取慢的问题
    MAC常用快捷键
    asi网络请求中遇到的一些问题的解决
    oc运行时runtime
    图片拉伸,气泡式
    ios nil、NULL和NSNull 的使用
    错误:linker command failed with exit code 1 (use v to see invocation)
    ios url 编码和解码
    SQL重置数据表id
  • 原文地址:https://www.cnblogs.com/10jschen/p/2648843.html
Copyright © 2020-2023  润新知