KMP例题—最小循环节—Lintcode1365—C++

删除回忆录丶 提交于 2020-02-10 13:10:07

本题是Lintcode上面的 KMP例题,困难属性。。。还是“限免题”,无力吐槽。

抄个题先—

1365. 最小循环节

中文English

给出一个int的数组 array, 求这个数组的最小循环节的长度。

样例

样例1

输入: [1,2,1,2,1,2]
输出: 2
说明:
最小循环节为[1,2],长度为2。

样例2

输入: [1,2,1,2,1]
输出: 2
说明:
最小循环节为[1,2],长度为2。最后一个2虽然没有给出,但是我们还是认为循环[1,2]。

样例3

输入: [1,2,1,2,1,4]
输出: 6
说明:
最小循环节为[1,2,1,2,1,4],长度为6。

注意事项

  • 数组大小不超过100000
  • 每个数int范围内。

 上代码!!!!先看下面的两个AC代码

代码1:

class Solution {
public:
    /**
     * @param array: an integer array
     * @return: the length of the minimum cycle section
     */
    int minimumCycleSection(vector<int> &array) {
        // Write your code here
        int len=array.size();
        vector<int>dp(len,0);
        dp[0]=0;
        for(int i=1;i<len;i++)
        {
            int p=dp[i-1];
            while(p!=0&&array[p]!=array[i])
            {
                p=dp[p-1];    
            }
            if(array[p]==array[i]) dp[i]=p+1;
            else dp[i]=0;
        }
        return len-dp[len-1];

    }
};

代码2: 

class Solution {
public:
    /**
     * @param array: an integer array
     * @return: the length of the minimum cycle section
     */
    int minimumCycleSection(vector<int> &array) {
        // Write your code here
        int len=array.size();
        vector<int>dp(len,0);
        dp[0]=-1;
        for(int i=1;i<len;i++)
        {
            int p=dp[i-1];
            while(p!=-1&&array[p+1]!=array[i])
            {
                p=dp[p];    
            }
            if(array[p+1]==array[i]) dp[i]=p+1;
            else dp[i]=-1;
        }
        return len-dp[len-1]-1;

    }
};

以上代码中的 dp[]对应的便是KMP中的next[]数组;

代码1中dp[i]的意义为:array[i]以及左边全部字符(包含array[i])组成的字符串中,前后缀相同的字符串长度

代码2中dp[i]的意义为:array[i]以及左边全部字符(包含array[i])组成的字符串中,前后缀相同的字符串中前缀字符串最后一个字符所在的地址;

 

其中尤其要注意的是:前后缀不得包含整个字符串!譬如,a的相同前后缀的长度是0而非1;abcabcabc的相同前后缀长度是6而非9;这是非常重要的一点!

 

然后以代码1为例:

最后的结果—最小循环节的长度=字符串总长度-前后缀相同的字符串长度,abcabcabc又可以当作不错的例子;

至于dp[]的具体应用,看代码自行体会。。。很智慧就是了。。。

 

除此之外,还有一种基于双指针的方法:

https://blog.csdn.net/littlekui74/article/details/99407275

感谢领扣喵!

这里直接引用一下图片!

在这里插入图片描述

使用左右双指针,如果满足条件双指针同时右移;不满足条件的话,左指针回到原点,而右指针不动。

但是在运行中败给了[1,1,1,3,2,1,1,1,1,3,2,1],答案应为6,但是输出了11.。。

其问题在于,当right在标红1—[1,1,1,3,2,1,1,1,1,3,2,1]位置后会一直右移,并且不会再回到“对”的1的位置—[1,1,1,3,2,1,1,1,1,3,2,1];

针对这种情况,我使用布尔值与tmp进行补充,即以下代码:

class Solution {
public:
    /**
     * @param array: an integer array
     * @return: the length of the minimum cycle section
     */
    int minimumCycleSection(vector<int> &array) {
        // Write your code here
        int left=0;
        int right=1;
        int ans=1;
        int tmp=1;
        bool flag=false;
        while(right<array.size())
        {
            
            
            if(array[left]==array[right])
            {
                if(left==0&&right<array.size()-1&&array[right]==array[right+1])
                {
                    flag=true;
                }
                left+=1;
                right+=1;
            
                
                
            }
            else if(array[left]!=array[right])
            {
                left=0;
                if(flag)
                {
                    right=tmp+1;
                    flag=false;
                }
                ans=right;
                
                if(array[left]!=array[right])
                {
                    right+=1;
                    ans=right;
                    tmp=right;
                }
            }
        }
        return ans;

    }
};

然而,在碰到下面这位后,就成功超时了,看来这就是KMP的强大所在,power! 

[1,2,3,4,5,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3 ...

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!