扩展KMP--求字符串S的所有后缀和字符串T的最长公共前缀
在解上面这个问题前我们要先解决一个类似的问题:求字符串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的最长公共前缀的更多相关文章
- hdu6153 扩展kmp求一个字符串的后缀在另一个字符串出现的次数。
/** 题目:hdu6153 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6153 题意:给定两个串,求其中一个串t的每个后缀在另一个串s中出现的次数乘以 ...
- hdoj 2594 Simpsons’ Hidden Talents 【KMP】【求串的最长公共前缀后缀】
Simpsons' Hidden Talents Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java ...
- [转][LeetCode]Longest Common Prefix ——求字符串的最长公共前缀
题记: 这道题不难但是很有意思,有两种解题思路,可以说一种是横向扫描,一种是纵向扫描. 横向扫描:遍历所有字符串,每次跟当前得出的最长公共前缀串进行对比,不断修正,最后得出最长公共前缀串. 纵向扫描: ...
- LeetCode -- 求字符串数组中的最长公共前缀
题目描写叙述: Write a function to find the longest common prefix string amongst an array of strings.就是给定1个 ...
- BNUOJ34990--Justice String (exkmp求最长公共前缀)
Justice String Given two strings A and B, your task is to find a substring of A called justice strin ...
- CSU1632Repeated Substrings(后缀数组/最长公共前缀)
题意就是求一个字符串的重复出现(出现次数>=2)的不同子串的个数. 标准解法是后缀数组.最长公共前缀的应用,对于样例aabaab,先将所有后缀排序: aab 3 aabaab 1 a ...
- python 字符串最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow&qu ...
- leetcode.字符串.14最长公共前缀-Java
1. 具体题目 编写一个函数来查找字符串数组中的最长公共前缀.如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","fl ...
- HDU 3613 Best Reward(扩展KMP求前后缀回文串)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分割 ...
随机推荐
- hibernate中的SessionFactory,Session分别表示什么啊?如何理解?
Session接口 Session接口对于Hibernate 开发人员来说是一个最重要的接口.然而在Hibernate中,实例化的Session是一个轻量级的类,创建和销毁它都不会 ...
- git版本库底层命令
当我们在使用git的时候,有时候需要知道当前文件夹相对于工作目录根目录的相对路径等等,那么我们可以使用 git rev-parse 添加一个参数就可以实现,如: 显示当前仓库版本库 .git 目录所在 ...
- Git使用简介
git创建分支并直接切换到分支:git checkout -b name git提交分支到远程服务器: git push origin name/git push origin name:name ...
- OLAP、OLTP的介绍和比较
OLTP与OLAP的介绍 数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing).联机分析处理OLAP(On-Line Analytical ...
- eclipse mingw cpp开发环境
Eclipse开发c++ 对比:微软的VC++6.0:太老了,对win7兼容不好, 现在微软的Visual Studio:安装包太大,好几个G,装了一堆你不需要的东西,要钱,教 育版申请麻烦 DOS下 ...
- APIO2015题解
分组赛讲课讲了APIO2015的题,于是回去就做完了 稍微写一点题解吧 bzoj4069 逐位处理的简单题,然后就是bool型dp 然后a=1 的时候可以把一位状态干掉 当一维状态单调且是bool型d ...
- ti processor sdk linux am335x evm /bin/setup-uboot-env.sh hacking
#!/bin/sh # # ti processor sdk linux am335x evm /bin/setup-uboot-env.sh hacking # 说明: # 本文主要对TI的sdk中 ...
- Java [Leetcode 190]Reverse Bits
题目描述: everse bits of a given 32 bits unsigned integer. For example, given input 43261596 (represente ...
- FFMPEG 库移植到 VC 需要的步骤
在VC下使用FFMPEG编译好的库,不仅仅是把.h,.lib,.dll拷贝到工程中就行了,还需要做以下几步.(此方法适用于自己使用MinGW编译的库,也同样适用于从网上下载的编译好的库,例如http: ...
- Darwin Streaming Server 简介
Darwin Streaming Server 概要 Darwin Streaming Server简称DSS.DSS是Apple公司提供的开源实时流媒体播放服务器程序.整个程序使用C++编写 ...