• HDU-3746 Cyclic Nacklace


    题意:给出一个字符串,然后假设其首尾连接,然后求其最小的循环节

    思路:

    要求循环节,通过运用next数组的含义。已知next数组为在该长度下的最长的相同前后缀长度

    然后利用关系式 sum = len - next[len] , sum - len%sum;

    然后就是关系式的解释:(关系刚开始理解了很久,主要是有些写的太含糊没有弄清,最后看了这个递归思路就理解了)

    例如字符串:

    1   2       3   4    5
    -------------------++++++++
    a b c d | a b c d | a b c d |a b c d       我们先不管其循环大小,先从next数组入手
          -------------------+++++++
    已知next  -1 0 0 0 1 2 3 4 5 6 7 8 9 10 11 12   (即上面的化横线加号部分相等)

    同时我们知道加号部分相等 (3 4)== (5 6) 那我们同时去掉 即 len - next[len];

    1       2       3   4    5
    ---------+++++++++
    a b c d | a b c d | a b c d      又重复上面的模型了 所以如过 len % (len - next[len]) == 0 除余数可以看作递归减去这个长度                    
          ---------++++++++      如果最后减没了则说明这个长度刚好是一个 循环的长度 即是所谓的循环节

    所以先判断有没有循环节

    有循环节 就可以判断 其是否刚好是循环节构成的 len%sum 即 len % (len - next[len]) == 0 此时就不必再补了 否则就补上 循环节所需的大小

    没有循环节 则要补充整个串(以整个串为单位)构成 新的节

    完整代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    
    using namespace std;
    const int maxn = 1e5+10;
    int nex[maxn];
    char a[maxn];
    int len;
    void getnext(){
        int i,j;
        i = 0,j = -1;
        nex[i] = j;
        while(i<len){
            if(j==-1||a[i]==a[j]) {
                nex[++i] =++j;
            }else j = nex[j];
        }
    }
    
    int main(){
        ios::sync_with_stdio(0);
        cin.tie(0);
        int T;
        cin>>T;
        while(T--){
    
            cin>>a;
            len = strlen(a);
            getnext();
            int sum=len-nex[len];
             if (!nex[len]) printf("%d
    ",len);
              else
                if (!(len%sum)) printf("0
    ");
                 else printf("%d
    ",sum-len%sum);
    
        }
    } 
  • 相关阅读:
    LeetCode90.子集 ||
    Ubuntu下的Matlab安装
    FAQ
    青石板
    交叉熵损失函数
    tf常用函数
    激活函数
    SGD和GD的区别
    卷积神经网络
    Ubuntu安装Matlab2016b
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11209190.html
Copyright © 2020-2023  润新知