KMP(最长重复子串 & 最小覆盖)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents

如果一个长度 L 字符串是由 n 个长度 L / n 子串构成的。那么最后一个字符的next值是L-L/n吧;

例如:

一个字符串:abbabbabbabbabb(一共15个字符)

next[15]=12吧!

我们拿:15 - 12 = 3 就是最长重复子串的长度

现在说一般情况:

假设 next[length] = k

如果 k % length == 0 那 length / k 就是最长重复子串长度;

如果 k 不能整除 length 那最长重复子串就是它自己了。

KMP,next[]表示模式串如果第i位(设T[0]为第0位)与文本串第j位不匹配,则要回到第next[i]位继续与文本串第j位匹配。则模式串第1位到next[n]与模式串第n-next[n]位到n位是匹配的。所以思路和上面一样,如果n%(n-next[n])==0,则存在重复连续子串,长度为n-next[n]。

例如:    a    b    a    b    a    b

next: -1   0    0    1    2    3    4

next[n] == 4代表着:前缀abab与后缀abab相等的最长长度,这说明,ab这两个字母为一个循环节,长度 = n-next[n];

求next[]值的代码如下:

#include<cstdio>
#include<cstring>
#define N 1000017
int next[N];
int len;
void getnext(char T[])
{
    int i = 0, j = -1;
    next[0] = -1;
    while(i < len)
    {
        if(j == -1 || T[i] == T[j])
        {
            i++;
            j++;
            next[i] = j;
        }
        else
            j = next[j];
    }

}
int main()
{
    char s[N];
    while(~scanf("%s",s))
    {
         len = strlen(s);
        getnext(s);
        for(int i = 1; i <= len; i++)
        {
            printf("%d ",next[i]);
        }
        printf("\n");
    }
    return 0;
}

实例运用见:http://blog.csdn.net/u012860063/article/details/38532507

KMP(最长重复子串 & 最小覆盖)

时间: 2024-11-05 21:54:44

KMP(最长重复子串 & 最小覆盖)的相关文章

DS串应用—最长重复子串

题目描述 求串的最长重复子串长度(子串不重叠).例如:abcaefabcabc的最长重复子串是串abca,长度为4. 输入 测试次数t t个测试串 输出 对每个测试串,输出最长重复子串长度,若没有重复子串,输出-1. 样例输入 3 abcaefabcabc szu0123szu szuabcefg 样例输出 4 3 -1 提示 #include<iostream> #include<string> using namespace std; int *getnext(string p

字符串中连续出现最多的子串 &amp; 字符串中最长重复子串

字符串中连续出现最多的子串 & 字符串中最长重复子串 字符串中连续出现最多的子串 & 字符串中最长重复子串,这两个问题都可以用后缀数组来表示,至于后缀数组可以参考编程珠玑P156:后缀数组就是定义一个数组指针,分别指向字符串中的对应位置,如下: a b c a b c a b c d e .substr[0] b c a b c a b c d e ....substr[1] c a b c a b c d e .......substr[2] a b c a b c d e ......

自己写的一个后缀树算法查找一个字符串的最长重复子串

在上个星期面试一家公司的笔试题上面的最后一道题就是写程序查找一个字符串的最长重复子串.当时想了很长时间没想出什么好方法,就把一个算法复杂度比较高的算法写上去了.回来上机把那个算法写了一遍测试没问题,然后自己又到网上面查查还有什么方法,然后发现好像有种叫做后缀树的方法,然后看那个方法,当时没给出代码,看图看了老半天加之自己想了好几个小时终于知道后缀树是个什么东西.然后自己萌生了一个自己写一个后缀树算法解决那个重复子串的问题.然后写了一天终于写出来了.后续有做了一些测试,发现自己写的一个只有几十个字

面试题[后缀数组]: 最长重复子串

题目:给定一个字符串,求出最长重复子串. 这个题目可以用后缀数组来解:对后缀数组排好序,这样重复的子串就在相邻的后缀中找就可以了.我的C++代码实现如下: class Solution { public: string LongestRepeatingSubstring(string str) { size_t len = str.size(); vector<string> SuffixArray(len); for (size_t i = 0; i < len; ++i) Suffi

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和

参考:http://www.ahathinking.com/archives/124.html 最长公共子序列 1.动态规划解决过程 1)描述一个最长公共子序列 如果序列比较短,可以采用蛮力法枚举出X的所有子序列,然后检查是否是Y的子序列,并记录所发现的最长子序列.如果序列比较长,这种方法需要指数级时间,不切实际. LCS的最优子结构定理:设X={x1,x2,……,xm}和Y={y1,y2,……,yn}为两个序列,并设Z={z1.z2.……,zk}为X和Y的任意一个LCS,则: (1)如果xm=

POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)

Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 14094   Accepted: 6244 Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation,

【POJ1743】不可重叠最长重复子串

题意:求一个字符串里两个不重叠的最长重复子串 代码如下: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 int sa[20010],rank[20010],y[20010],Rsort[20010]; 8 int wr[20010],a[20010],height[20010],n; 9 10

POJ 3080 Blue Jeans(KMP 最长公共子串)

Blue Jeans Description The Genographic Project is a research partnership between IBM and The National Geographic Society that is analyzing DNA from hundreds of thousands of contributors to map how the Earth was populated. As an IBM researcher, you ha

POJ 3261 可重叠的 k 次最长重复子串【后缀数组】

这也是一道例题 给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠.算法分析:这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组.不同的是,这里要判断的是有没有一个组的后缀个数不小于 k.如果有,那么存在k 个相同的子串满足条件,否则不存在.这个做法的时间复杂度为 O(nlogn). Source Code: //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include