KMP算法 - 求最小覆盖子串
KMP与最小覆盖子串
最小覆盖子串:对于某个字符串s,它的最小覆盖子串指的是长度最小的子串p,p满足通过自身的多次连接得到q,最后能够使s成为q的子串。
比如:
对于s="abcab",它的最小覆盖子串p="abc",因为p通过在它后面再接上一个p(即重叠0个字符),可以得到q="abcabc",此时s是q的子串。
对于s="ababab",它的最小覆盖子串为p="ab"。
根据KMP算法的next数组的定义,设字符串s的长度为n,则next[n] = next[n - 1],n-1为s的最后一位。
next[n]表明s[0,1,2,...,next[n]-1] == s[n-next[n],...,n-1],设这两段分别为s1和s2。
若s1和s2的长度之和小于s的长度,则说明s1和s2分别为不重叠的前缀和后缀,则最小覆盖子串必为s截去s2之后得到的前缀。
若s1和s2的长度之和大于等于s的长度,则最小覆盖子串也必为s截去s2之后得到的前缀。
以上两种情况都可以推出这个结论:最小覆盖子串是s的前缀,它的长度为n-next[n]。
我对KMP的一些理解(lyp点拨的):pre[i](或next[i])的实质是串str[1..i]的最长且小于i的“相等前、后缀”分别为str[1..pre[i]](前缀)与str[(i-pre[i]+1)..i](后缀),通俗讲就是:使str[1..i]前k个字母与后k个字母相等的最大k值。
KMP算法详解可见:http://blog.csdn.net/fjsd155/article/details/6864233
另外一个结论:
最小覆盖子串(串尾多一小段时,用前缀覆盖)长度为n-next[n](n-pre[n]),n为串长。
证明分两部分:
1-长为n-next[n]的前缀必为覆盖子串。
当next[n]<n-next[n]时,如图a,长为next[n]的前缀A与长为next[n]的后缀B相等,故长为n-next[n]的前缀C必覆盖后缀B;

当next[n]>n-next[n]时,如图b,将原串X向后移n-next[n]个单位得到Y串,根据next的定义,知长为next[n]的后缀串A与长为前缀串B相等,X串中的长为n-next[n]的前缀C与Y串中的前缀D相等,而X串中的串E又与Y串中的D相等……可见X串中的长为n-next[n]的前缀C可覆盖全串。

2-长为n-next[n]的前缀是最短的。
如图c,串A是长为n-next[n]的前缀,串B是长为next[n]的后缀,假设存在长度小于n-next[n]的前缀C能覆盖全串,则将原串X截去前面一段C,得到新串Y,则Y必与原串长度大于next[n]的前缀相等,与next数组的定义(使str[1..i]前k个字母与后k个字母相等的最大k值。)矛盾。得证!有人问,为什么Y与原串长大于next[n]的前缀相等?由假设知原串的构成必为CCC……E(E为C的前缀),串Y的构成必为CC……E(比原串少一个C),懂了吧!

最后得出结论:总长度-next[n].
code:
// Memory Time
// 1347K 0MS
// by : Snarl_jsb
// 2014-10-02-21.08
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<climits>
#include<cmath>
#define N 1000010
#define LL long long
using namespace std; string str;
vector<int> next;
void GetNext()
{
int len=str.size();
next.push_back();
int k=;
for(int i=;i<len;++i)
{
if(k!=&&str[i]!=str[k])
k=next[k-];
if(str[i]==str[k])
k++;
next.push_back(k);
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie();
// freopen("C:\\Users\\ASUS\\Desktop\\cin.cpp","r",stdin);
// freopen("C:\\Users\\ASUS\\Desktop\\cout.cpp","w",stdout);
while(cin>>str)
{
next.clear();
int len=str.size();
GetNext();
// for(int i=0;i<len;++i)
// {
// cout<<len-next[i]<<endl;
// }
cout<<"最小覆盖子串为:"<<len-next[len-]<<endl;
}
return ;
}
KMP算法 - 求最小覆盖子串的更多相关文章
- POJ 2185 Milking Grid (KMP,求最小覆盖子矩阵,好题)
题意:给出一个大矩阵,求最小覆盖矩阵,大矩阵可由这个小矩阵拼成.(就如同拼磁砖,允许最后有残缺) 正确解法的参考链接:http://poj.org/showmessage?message_id=153 ...
- POJ 3450 Corporate Identity (KMP,求公共子串,方法很妙)
http://blog.sina.com.cn/s/blog_74e20d8901010pwp.html我采用的是方法三. 注意:当长度相同时,取字典序最小的. #include <iostre ...
- KMP算法字符串查找子串
题目: 经典的KMP算法 分析: 和KMP算法对应的是BF算法,其中BF算法时间复杂度,最坏情况下可以达到O(n*m),而KMP算法的时间复杂度是O(n + m),所以,KMP算法效率高很多. 但是K ...
- HDU-3746 Cyclic Nacklace 字符串匹配 KMP算法 求最小循环节
题目链接:https://cn.vjudge.net/problem/HDU-3746 题意 给一串珠子,我们可以在珠子的最右端或最左端加一些珠子 问做一条包含循环珠子的项链,最少还需要多少珠子 思路 ...
- poj3020 Antenna Placement 匈牙利算法求最小覆盖=最大匹配数(自身对应自身情况下要对半) 小圈圈圈点
/** 题目:poj3020 Antenna Placement 链接:http://poj.org/problem?id=3020 题意: 给一个由'*'或者'o'组成的n*m大小的图,你可以用一个 ...
- POJ-2752 Seek the Name, Seek the Fame 字符串问题 KMP算法 求前后缀串相同数木
题目链接:https://cn.vjudge.net/problem/POJ-2752 题意 给一个字符串,求前缀串跟后缀串相同的前缀串的个数 例:alala 输出:a, ala, alala 思路 ...
- HDU-1358 Period 字符串问题 KMP算法 求最小循环节
题目链接:https://cn.vjudge.net/problem/HDU-1358 题意 给一个字符串,对下标大于2的元素,问有几个最小循环节 思路 对每个元素求一下minloop,模一下就好 提 ...
- kmp算法,求重复字符串
public class Demo { public static void main(String[] args) { String s1 = "ADBCFHABESCACDABCDABC ...
- hdoj 3336 Count the string【kmp算法求前缀在原字符串中出现总次数】
Count the string Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
随机推荐
- Vmware9.0打开早期版本报错:this virtual machine’s policies are too old to be run by this version of vmware workstation”
VMWare从6.0升级到9.0,打开以前的虚拟机报错如下: “this virtual machine’s policies are too old to be run by this versio ...
- 老罗学习MVC之旅:MVC组件分析
2System.Web.Mvc V 4.0.0.0 组件分析 2.1 Routing组件(路由选择) Routing的作用就是负责分析Url Action的要求• 必须是一个公有方法• 必须返回A ...
- .net微信公众号开发——快速入门
作者:王先荣 最近在学习微信公众号开发,将学习的成果做成了一个类库,方便重复使用. 现在微信公众号多如牛毛,开发微信的高手可以直接无视这个系列的文章了. 使用该类库的流程及寥寥数行代码得到的结果如下. ...
- iOS各个版本的新特性介绍
官方汇总 What's News in iOS iOS 9.3 to iOS 10.0 API Differences Objective-C /usr/include Accelerate Audi ...
- Javascript类继承-机制-代码Demo【原创】
最近看到<Javascript设计模式>,对js模拟的”继承方式“有了更深一步的了解,虽然之前也总是用到prototype.new ,但只是知其然不知所以然,现在将类继承的方法整理如下,暂 ...
- Linux进程通信 之 信号灯(semphore)(System V && POSIX)
一. 信号灯简介 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机制. 相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源,同时,进程 也可以修改该标志.除了用于访 ...
- 在Windows/Ubuntu下安装OpenGL环境(GLUT/freeglut)与跨平台编译(mingw/g++)
GLUT/freeglut 是什么? OpenGL 和它们有什么关系? OpenGL只是一个标准,它的实现一般自带在操作系统里,只要确保显卡驱动足够新就可以使用.如果需要在程序里直接使用OpenGL, ...
- 二十五、【开源】EFW框架Winform前端开发之强大的自定义控件库
回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.2:http://pan.baidu.com/s/1hcnuA EFW框架实例源代码下载:http://pan ...
- react-native Unrecognized font family ‘Lonicons’;
在使用:react-native-vector-icons库时报的错. 解决办法:使用这个库时android和ios工程目录中需要做些配置 配制方法如下: http://www.cnblogs.com ...
- adb permission denied
1.没有得到root权限,可以用刷机精灵一键root. 2.root不彻底,手机安装超级adbd,即可.