在解上面这个问题前我们要先解决一个类似的问题:求字符串s的所有后缀和s本身的最长公共前缀;

我们用next[]数组保存这些值;

现在我们假设要求next[ x ],并且next[ i ] 0<i<x的值都已经求出;

我们设p = k + next[k] - 1, k是使p最大的 i  (0<i<x);如图:

现在整理一下问题:

  已知:s[k..p] == s[ 0 .. next[ k ]-1 ],求s[x .. n-1]与s[0 .. n-1]的最长公共前缀;

  由s[k .. p] == s[ 0 .. next[ k ]-1 ] 得:

s[x .. p] == s[x-k .. next[ k ]-1 ]    ---------1//这个是显然的

并设L1=p-x+1;

因为x-k肯定是小于x的所以  L2=next[x-k]是已知的,得:

s[0 ..  L2-1] == s[x-k .. x-k+L2-1];      --------2

通过等式1,2可以推出 s[0 .. k1] == s[x .. k2]

if  L1<=L2  then  如下图

表示s[0 .. L1-1] == s[x .. x+L1-1]但不能确定蓝色部分是否相等,所以需要继续比下去

if  L1 > L2   then 如下图:

表示s[0 ..  L2-1] == s[x .. x+L2-1] 而且因为L2 = next[x-k]使得s[L2] != s[x+L2]

所以next[x] = L2;

证明:假设s[L2]==s[x+L2],又因为s[x+L2]==s[x-k+L2]//由1推出

所以s[L2]==s[x-k+L2] 所以next[x-k]==L2+1与next[x-k]==L2矛盾

 void getNext(char *s,int next[]){
int nn = strlen(s);
next[] = nn;
int p = ;
while (p+ < nn && s[p] == s[p+]) p++;
next[] = p;
int k = , L;
for (int i = ; i < nn; i++){
p = k + next[k] - ; L = next[i - k];
if (i + L <= p) next[i] = L;
else {
int j = p - i + ;
if (j < ) j = ;
while (i + j < nn && s[i + j] == s[j]) j++;
next[i] = j; k = i; }
}
/* for (int i=0;i<nn;i++){
cout<< next[i] <<" ";
}cout<<endl;
*/
}

回到原来的问题

此时已经求出next[],我们用extend[]保存字符串S的所有后缀和字符串T的最长公共前缀的值

我们重复上面的过程:

现在我们假设要求extend[ x ],并且extend[ i ] 0<i<x的值都已经求出;

我们设p = k + extend[k] - 1, k是使p最大的 i  (0<i<x);如图:

现在整理一下问题:

  已知:s[k..p] == T[ 0 .. extend[ k ]-1 ],求s[x .. n-1]与T[0 .. m-1]的最长公共前缀;

  由s[k .. p] == T[ 0 .. extend[ k ]-1 ] 得:

s[x .. p] == T[x-k .. extend[ k ]-1 ]    ---------1//这个是显然的

并设L1=p-x+1;

因为x-k肯定是小于x的所以  L2=next[x-k]是已知的,得:

T[0 ..  L2-1] == T[x-k .. x-k+L2-1];      --------2

通过等式1,2可以推出 T[0 .. k1] == s[x .. k2]

if  L1<=L2  then  如下图

表示T[0 .. L1-1] == s[x .. x+L1-1]但不能确定蓝色部分是否相等,所以需要继续比下去

if  L1 > L2   then 如下图:

表示T[0 ..  L2-1] == s[x .. x+L2-1] 而且因为L2 = extend[x-k]使得T[L2] != s[x+L2]

所以extend[x] = L2;

证明:假设T[L2]==s[x+L2],又因为s[x+L2]==T[x-k+L2]//由1推出

所以T[L2]==s[x-k+L2] 所以extend[x-k]==L2+1与extend[x-k]==L2矛盾

 void getExtend(char *s,char *T,int extend[]){
int nn = strlen(s) ,mm = strlen(T);
getNext(s,next);
int p = ;
while (p < nn && s[p] == T[p]) p++;
extend[] = p;
//extend[1] = p;
int k = , L;
for (int i = ; i < nn; i++){
p = k + extend[k] - ; L = next[i - k];
if (i + L <= p) extend[i] = L;
else {
int j = p - i + ;
if (j < ) j = ;
while (i + j < nn && s[i + j] == T[j]) j++;
extend[i] = j; k = i; }
}
/* for (int i=0;i<nn;i++){
cout<< extend[i] <<" ";
}cout<<endl;
*/
}

时间复杂度分析:

对于s串,每一位最多比较一次所以时间是O(n)的;

扩展KMP--求字符串S的所有后缀和字符串T的最长公共前缀的更多相关文章

  1. hdu6153 扩展kmp求一个字符串的后缀在另一个字符串出现的次数。

    /** 题目:hdu6153 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6153 题意:给定两个串,求其中一个串t的每个后缀在另一个串s中出现的次数乘以 ...

  2. hdoj 2594 Simpsons’ Hidden Talents 【KMP】【求串的最长公共前缀后缀】

    Simpsons' Hidden Talents Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java ...

  3. [转][LeetCode]Longest Common Prefix ——求字符串的最长公共前缀

    题记: 这道题不难但是很有意思,有两种解题思路,可以说一种是横向扫描,一种是纵向扫描. 横向扫描:遍历所有字符串,每次跟当前得出的最长公共前缀串进行对比,不断修正,最后得出最长公共前缀串. 纵向扫描: ...

  4. LeetCode -- 求字符串数组中的最长公共前缀

    题目描写叙述: Write a function to find the longest common prefix string amongst an array of strings.就是给定1个 ...

  5. BNUOJ34990--Justice String (exkmp求最长公共前缀)

    Justice String Given two strings A and B, your task is to find a substring of A called justice strin ...

  6. CSU1632Repeated Substrings(后缀数组/最长公共前缀)

    题意就是求一个字符串的重复出现(出现次数>=2)的不同子串的个数. 标准解法是后缀数组.最长公共前缀的应用,对于样例aabaab,先将所有后缀排序: aab 3    aabaab 1    a ...

  7. python 字符串最长公共前缀

      编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow&qu ...

  8. leetcode.字符串.14最长公共前缀-Java

    1. 具体题目 编写一个函数来查找字符串数组中的最长公共前缀.如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","fl ...

  9. HDU 3613 Best Reward(扩展KMP求前后缀回文串)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分割 ...

随机推荐

  1. Codeforces Round #271 (Div. 2)

    A. Keyboard 题意:一个人打字,可能会左偏一位,可能会右偏一位,给出一串字符,求它本来的串 和紫书的破损的键盘一样 #include<iostream> #include< ...

  2. IIS修改队列长度(IIS6+IIS7)

    Internet Information Services (IIS) 限制了在任何给定时间可在队列中等待的应用程序池请求的最大数量.如果达到此限制,则所有新请求都将被拒绝,而且用户将收到错误消息“5 ...

  3. ASP.NET MVC @helper使用说明

    简单的 @helper 方法应用场景 Razor中的@helper语法让您能够轻松创建可重用的方法,此方法可以在您的视图模板中封装输出功能.他们使代码能更好地重用,也使代码更具有可读性. 在我们定义@ ...

  4. js 跨域的问题 (同一个主域名不同的二级域名下的跨域问题) 解决 WdatePicker.js my97日期选择控件

    例如域名是  a.xx.com  和 b.xx.com    如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain. 如果iframe的时候  a包含b  为 ...

  5. I.MX6 Android U-blox miniPCI 4G porting

    /************************************************************************** * I.MX6 Android U-blox m ...

  6. wap版和pc版的旋转js

    <script type="text/javascript"> var evt = "onorientationchange" in window ...

  7. 把一个类(或者Object)转换成字典

    直接上代码:把一个类转换成object,然后在转换成字典 internal static IDictionary<string, string> GetDictionary(this ob ...

  8. 用ioctl获取无线网络信息 /usr//include/linux/wireless.h

    1.UNIX Network Programming环境搭建 Unix NetWork Programming――环境搭建(解决unp.h等源码编译问题) http://blog.csdn.net/a ...

  9. fastdb中的位图应用

    位图内存管理: 每块内存用一个二进制位表示它的使用状态,如果该块内存被占用,则把对应位图中的对应位置1,如果空闲则置0,原理十分简单.计算机里面处理的位数最少的变量是字节(byte),所以也就是8位做 ...

  10. 【转】STL空间配置器

    STL空间配置器(allocator)在所有容器内部默默工作,负责空间的配置和回收.STL标准为空间配置器定义了标准接口(可见<STL源码剖析>P43).而具体实现细节则由各编译器实现版本 ...