本题是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 ...
来源:CSDN
作者:小孩子少吃糖
链接:https://blog.csdn.net/qq_40607199/article/details/104244145