kmp(二)

Cyclic Nacklace HDU - 3746

题目链接:https://cn.vjudge.net/contest/163024#problem/D
题目大意:给你一个字符串,要求将字符串的全部字符最少循环2次需要添加的字符数。
例子:abcabc 已经循环2次,添加数为0
abcac 没有循环2次,添加字符abcac。数目为5.
abcabcab 已经循环过2次,但第三次不完整,需要添加数为1
题目分析:求循环节

      get_next();
      int min_repeat = len - Next[len - 1]; //最小循环节
      if(len % min_repeat == 0 && len / min_repeat > 1) //len / min_repeat 是为了防止一个字符的情况
      //if(len- (len - nexts[len]) > 0 && len%min_repeat==0) 也是对的
              printf("0\n");
      else
         printf("%d\n", min_repeat - (len % min_repeat));

为什么len - Next[len - 1]是最小循环节?
因为abcefgabc Next[len - 1] = 3,这是后缀与前缀的最大匹配个数,说明从abc又开始循环了,所以len - Next[len - 1]是循环节。
abcabcabcab 这种我也不懂怎么解释。
这里的循环节是说它应该的循环节,而不是说它真正的循环节。

Period HDU - 1358

题目链接:https://cn.vjudge.net/contest/163024#problem/E
题目大意:求字符串的前缀是否为周期串,若是,打印循环节的长度及循环次数;
题目分析:遍历每一个位置,判断循环节即可
例子:
3
aaa
Test case #1
2 2
3 3

12
aabaabaabaab
Test case #2
2 2
6 2
9 3
12 4

int main()
{
     int cas = 1, i;
     while(~scanf("%d", &len) && len)
     {
        scanf("%s", s);
        get_next();
        printf("Test case #%d\n", cas++);
        for(i = 1; i <= len; i++)
        {
            int min_repeat = i - Next[i - 1];
            if(i % min_repeat == 0 && i / min_repeat > 1)
                printf("%d %d\n", i, i / min_repeat);
        }

        printf("\n");
     }
     return 0;
}

Seek the Name, Seek the Fame POJ - 2752

题目链接:https://cn.vjudge.net/contest/163024#problem/H
题目分析:给定一个字符串s,从小到大输出s中既是前缀又是后缀的子串的长度。
例子: input :ababcababababcabab output: 2 4 9 18

int main()
{
    int i;
     while(~scanf("%s", s)) {
         len = strlen(s);
         get_next();

         int cnt = 0;
         int t = Next[len - 1];
         ans[cnt++] = len;
         while(t > 0) {
           if(s[len - 1] == s[t - 1]) {
              ans[cnt++] = t;
           }
           t = Next[t - 1];
       }
        for(i = cnt - 1; i >= 0; i--)
            printf("%d%c", ans[i], i == 0 ? '\n' : ' ');
     }
     return 0;
}

Count the string HDU - 3336

题目链接:https://cn.vjudge.net/contest/163024#problem/K
题目大意:给定一字符串,求该串的前缀在该串中的出现次数。
题目样例:
1
4
abab “a”出现l两次, “ab”出现两次, “aba”一次, “abab”一次 2+2+1+1 = 6
题目分析:
举个例子。
abababa**b**cab
00123456012
依旧是next数组的应用,首先每个前缀一定会出现一次,一共有n个。
当next[i] + 1 != next[i + 1] 时,就说明到这个位置,和前缀能匹配上,例子中b位置断开,Next[b] = 6,说明从当前位置向前六个跟前缀一样,就是说有六个前缀又出现了一次,这时候sum+= Next[b]。

int main()
{
    int t, n, i, sum;
    scanf("%d", &t);
    while(t--)  {
        scanf("%d", &n);
        scanf("%s", str);
        get_next();

        sum = n + Next[n - 1];
        sum %= 10007;
        for(i = 0; i < n - 1; i++) {
            if(Next[i] + 1 != Next[i + 1]) {
                sum += Next[i];
                sum %= 10007;
            }

        }

        printf("%d\n", sum % 10007);
    }
     return 0;
}

猜你喜欢

转载自blog.csdn.net/deerly_/article/details/79961649
kmp
今日推荐