KMP - LeetCode #459 Repeated Substring Pattern
复习一下KMP算法
KMP的主要思想是利用字符串自身的前缀后缀的对称性,来构建next数组,从而实现用接近O(N)的时间复杂度完成字符串的匹配
对于一个字符串str,next[j] = k 表示满足str[0...k-1] = str[j-k...j-1]的最大的k,即对于子串str[0...j-1],前k个字母等于后k个字母
现在求解str的next数组:
初始化:next[0] = -1
那么在知道了next[j]的情况下,如何递推地求出next[j+1]呢?分两种情况(令k=next[j]):
1、如果str[j]==str[k],则next[j+1] = k+1
如下图所示,对于str[0...j-1],前k个字母等于后k个字母(两个绿色部分相等),然后str[k]刚好是前k个字母的下一个字母(第一个红色)
如果str[j]==str[k],说明对于str[0...j],前k+1个字母等于后k+1个字母(绿色+红色=绿色+红色),即等于next[j]+1(绿色长度为k,红色长度为1)
2、如果str[j]!=str[k],则k=next[k],然后继续循环(回到1),直到k=-1
因为str[j]!=str[k](下图中紫色和红色不相等),所以前k+1个字母不再等于后k+1个字母了
但是由于前k个字母还是等于后k个字母(图中两个黑色虚线框住部分),所以对于任意的k'<k,str[k-k'...k-1]=str[j-k'...j-1](图中第二个和最后一个绿色相等)
而next[k]表示str[0...k-1]内部的对称情况,所以令k'=next[k],则对于str[0...k-1],前k'个字母等于后k'个字母(图中第一个和第二个绿色相等)
由于图中第二个绿色始终=第四个绿色,所以第一个绿色等于第四个绿色
因此将k=next[l]继续带入循环,回到判断1:
如果str[k']=str[j],则满足前k'+1个字母等于后k'+1个字母(两个浅黄色区域相等),所以next[j+1] = k'+1;
否则,继续k'=next[k']继续循环,直到k'=-1说明已经到达第一个元素,不能继续划分,next[j+1]=0
得到了求next数组的递推方法后,现在用C++实现
void getNext( string str, int next[] )
{
int len = str.length();
next[0] = -1;
int j = 0, k = -1;
while( j<len-1 )
{
if( k==-1 || str[j]==str[k] )
next[++j] = ++k;
else
k = next[k];
}
}
这里解释一下:由于每一轮赋值完next[j]后,k要不然是-1,要不然是next[j](上次匹配的前缀的下一个位置)
如果k=-1,说明next[j+1]=0=k+1;否则如果str[j]==str[k],说明前k+1个字母等于后k+1个字母,直接next[j+1]=k+1
所以循环中if后的语句为“next[++j] = ++k;”
现在用求解next数组的思路解决leetcode上的一道题
https://leetcode.com/problems/repeated-substring-pattern/
Given a non-empty string check if it can be constructed by taking a substring of it and appending multiple copies of the substring together. You may assume the given string consists of lowercase English letters only and its length will not exceed 10000
Example:
Input: "abcabcabcabc" Output: True Explanation: It's the substring "abc" four times. (And the substring "abcabc" twice.)
假设str长度为len,重复的子串长度为k,则如果真的由连续多个长度为k的子串重复构成str,那么在对str求next时,由于连续对称性(如图,前后两个虚线框内字符串相等),会从next[k+1]开始,1,2,3...地递增,直到next[len]=len-k,且(len-k)%k==0,表示有整数个k
要一直求到next[len]而不是next[len-1],是因为next[len-1]只是表示前len-1个字母的内部对称性,而没有考虑到最后一个字母即str[len-1]
所以求解很简单:先对str求next数组,一直求到next[len],然后看看next[len]是否非零且整除k(k=len-next[len])
bool repeatedSubstringPattern(string str)
{
int len = str.length();
int next[len+1];
next[0] = -1;
int j = 0, k = -1;
while( j<len )
{
if( k==-1 || str[j]==str[k] )
next[++j] = ++k;
else k = next[k];
}
return next[len]&&next[len]%(len-next[len])==0;
}
时间复杂度只有O(N),而暴力需要O(N^2)
KMP - LeetCode #459 Repeated Substring Pattern的更多相关文章
- 43. leetcode 459. Repeated Substring Pattern
459. Repeated Substring Pattern Given a non-empty string check if it can be constructed by taking a ...
- [LeetCode] 459. Repeated Substring Pattern 重复子字符串模式
Given a non-empty string check if it can be constructed by taking a substring of it and appending mu ...
- LeetCode - 459. Repeated Substring Pattern - O(n)和O(n^2)两种思路 - KMP - (C++) - 解题报告
题目 题目链接 Given a non-empty string check if it can be constructed by taking a substring of it and appe ...
- LeetCode 459 Repeated Substring Pattern
Problem: Given a non-empty string check if it can be constructed by taking a substring of it and app ...
- 459. Repeated Substring Pattern【easy】
459. Repeated Substring Pattern[easy] Given a non-empty string check if it can be constructed by tak ...
- 459. Repeated Substring Pattern
https://leetcode.com/problems/repeated-substring-pattern/#/description Given a non-empty string chec ...
- *459. Repeated Substring Pattern (O(n^2)) two pointers could be better?
Given a non-empty string check if it can be constructed by taking a substring of it and appending mu ...
- 【LeetCode】459. Repeated Substring Pattern
Given a non-empty string check if it can be constructed by taking a substring of it and appending mu ...
- 【LeetCode】459. Repeated Substring Pattern 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 遍历子串 日期 [LeetCode] 题目地址:ht ...
随机推荐
- jQuery和AngularJS的区别
这篇文章主要介绍了jQuery和AngularJS的区别浅析,本文着重讲解一个熟悉jQuery开的程序员如何应对AngularJS中的一些编程思想的转变,需要的朋友可以参考下 最近一直在研究ang ...
- win10 uwp 自定义控件初始化
我遇到一个问题,我在 xaml 用了我的自定义控件,但是我给他设置了一个值,但是什么时候我才可以获得这个值? 本文告诉大家,从构造函数.loaded.Initialized 的调用过程. 用最简单的方 ...
- win10 uwp 如何拖动一个TextBlock的文字到另一个TextBlock
我在堆栈网看到有人问 如何拖动一个TextBlock的文字到另一个TextBlock 于是看到一个大神给出的方法,下面我就来和大家说下如何拖动 一开始我们需要一个界面,就放两个TextBlock 一个 ...
- Java IO(Properties/对象序列化/打印流/commons-io)
Java IO(Properties/对象序列化/打印流/commons-io) Properties Properties 类表示了一个持久的属性集.Properties 可保存在流中或从流中加载. ...
- 【JAVA零基础入门系列】Day10 Java中的数组
什么是数组?顾名思义,就是数据的组合,把一些相同类型的数放到一组里去. 那为什么要用数组呢?比如需要统计全班同学的成绩的时候,如果给班上50个同学的成绩信息都命名一个变量进行存储,显然不方便,而且在做 ...
- LeetCode 532. K-diff Pairs in an Array (在数组中相差k的配对)
Given an array of integers and an integer k, you need to find the number of unique k-diff pairs in t ...
- Linux系列教程(六)——Linux文件搜索命令
前一篇博客我们讲解了Linux链接命令和权限管理命令, 通过 ln -s 链接名 表示创建软链接,不加-s表示创建硬链接:还有三个更改权限的命令,chmod命令可以更改文件或目录权限,chown命令 ...
- BigDecimal与Long之间的转换
新建了一个class类 取名叫Firut import java.math.BigDecimal; public class Firut { private String id; private Bi ...
- C#设计模式--简单工厂模式
简单工厂模式是属于创建型模式,但不属于23种GOF设计模式之一. 举一个例子:一个公司有不同的部门,客户根据需要打电话到不同的部门.客户相当于上端,不同部门相当于下端.不使用简单工厂模式来实现的例子如 ...
- AJAX,PHP,前端简单交互制作输入框效果
PHP数据 <?php // 数据 $arr = array( array("百度", "http://www.baidu.com/"), array(& ...