问题描述
:设T是长为n的文本串。描述一个找出T的最长前缀的O(n)时间的方法,该前缀也是T的逆串的一个子串。
(来自《Algorithm Design》(中文版:算法分析与设计) -
Chapter9 - 文本处理 - 创新题C-9.12)
分析:既然要在O(n)时间内完成,KMP算法是可以考虑的。根据题目要求我们发现要让T的前缀匹配到T的逆串。那么我们可以把T的逆串作为主串,T作为模式串。对KMP算法做如下修改:
(1) 在匹配逻辑中,主串指针 i 从T逆向开始查找,即i=(T.length-1) ——> 0。模式串指针 j 从T正向开始查找,即j=0 ——> (T.length-1)。这样就不用首先做T逆向的处理了。
(2) 每一次T[i]==T[j](i 为T的逆序指针,j为T的顺序指针),都用一个字符串累加起来。直到遇上不相等的时候,则保留原字符串,清空后重新开始累加。直到 i=0为止。此时,所有保留的字符串都是满足条件的T的前缀子串,在比较长度取出最大的字符串即可。
Java代码如下:
public class SelfKMP {
private int[] next=null;
private char[] mainAry=null;
//记录匹配上的所有前缀
ArrayList<String> path=new ArrayList<String>();
public KMP(String main){
this.mainAry=new char[main.length()+1];
System.arraycopy(main.toCharArray(),0,mainAry,1,main.length());
this.next=new int[main.length()+1];
}
/**
* KMP匹配
* @param pos 从主串起始位置开始
*/
public String maxMatch(){
failFunction();
int i=mainAry.length-1;
int j=1;
String temp="";
while(i>0&&j<mainAry.length){
if(j==0||mainAry[i]==mainAry[j]){
if(j!=0)
temp=temp+mainAry[j]; //记录每一次想等的字符
--i;
++j;
}else{
array.add(temp);
temp="";
j=next[j];
}
}
String maxPreStr="";
for(String s:array){
if(s.length>maxPreStr.length){
maxPreStr=s;
}
}
return maxPreStr;
}
/**
* 匹配串失效函数
*/
private void failFunction(){
int i=1,j=0;
next[1]=0;
while(i<mainAry.length-1){
if(j==0||mainAry[i]==mainAry[j]){
next[++i]=++j;
}else{
j=next[j];
}
}
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
SelfKMP kmp=new SelfKMP("acabaabaabcacaabc");
System.out.println(kmp.maxMatch());
}
}
效率: 这个算法和KMP没有什么不同,因此n长度的T串最先需要付出O(n)代价来计算T的失效函数。然后需要O(n)来匹配前缀,最后付出O(x)代价来找最大字符串,其中x<n为所有满足条件的T前缀串的数量。
分享到:
相关推荐
#### 1.4 <算法书>最长前缀是逆串的子串 - **问题描述**:找出字符串的最长前缀,该前缀也是其逆序字符串的子串。 - **解决方案**: - 将原字符串与其逆序字符串拼接起来。 - 使用KMP算法找到最长的相同前缀。 - ...
通过计算LCP(Longest Common Prefix,最长公共前缀)数组,可以找出两个或多个字符串的最长公共子串。LCP数组是基于后缀数组的,表示相邻两个后缀的最长公共前缀的长度。源码实现这部分功能有助于读者更好地掌握...
后缀数组的构建和应用通常涉及到字符串的最长公共前后缀、最长重复子串、最长回文子串等问题。 首先,我们来看【POJ 1743】这个问题,它要求找出一个乐曲序列中满足特定条件的最长重复主题。这里的条件包括主题长度...
9. **后缀数组和后缀树**:这两种数据结构是处理字符串问题的强大工具,常用于最长公共前缀、最长重复子串等问题,也可用于高效的字符串匹配。 10. **Manacher's Algorithm**:针对奇偶回文子串的高效查找,...
KMP(Knuth-Morris-Pratt)算法是一种在文本串(text)中查找子串(pattern)的著名字符串搜索算法,由Donald Knuth、 Vaughan Pratt和James Morris三人提出。这个算法避免了对已匹配部分的重复比较,提高了效率。在...
4. **滑动窗口**:在处理长字符串时,滑动窗口技术允许我们在固定大小的窗口内检查子串,这在计算最频繁出现的子串或寻找最长公共子串等问题中很有用。 5. **编辑距离**:也称为Levenshtein距离,它衡量两个字符串...
5. **字符串处理**:包括字符串匹配(如KMP算法)、最长公共前缀、最长回文子串等,这些在文本处理和信息检索等领域至关重要。 6. **图论算法**:如最小生成树(Prim或Kruskal算法)、最短路径(Dijkstra或Floyd...
这一步可以通过动态规划实现,对于模式串中的每个位置i,计算最长的前缀和后缀相同的部分,长度记为`pi`。 2. 然后,从文本串的第一个字符开始,逐个字符与模式串进行比较。如果匹配成功,则移动模式串的下一个字符...
8. **字符串处理**:KMP算法、Rabin-Karp算法等用于模式匹配,Z算法和Manacher's算法用于找出字符串中的最长回文子串。 9. **编码技巧**:如位运算、前缀和、 Fenwick树(也称作二分查找树)和Segment Tree等,这些...
KMP算法的核心是预处理模式串,构建一个next数组,这个数组记录了模式串在不同位置上的最长公共前缀与最长公共后缀的长度。在进行字符串匹配时,若发生不匹配,可通过next数组直接跳过那些不可能匹配的字符,避免了...
- **特定算法题目的解决**:如判断字符串的旋转,求最长无重复字符子串等。 这本书通过详尽的算法题目和知识点,提供了一个完整的面试准备方案,不仅涉及了传统的数据结构和算法,还包括了一些高级数据结构与算法,...
- **最长公共前缀**:在后缀树中,从根节点到任何内部节点的路径代表了一个共享前缀,最长的路径即为最长公共前缀。 - **模式计数**:计算一个模式在字符串中出现的次数。 - **基因序列比对**:在生物信息学中,后缀...
9. **字符串处理**:KMP算法、Boyer-Moore算法、Rabin-Karp算法等用于字符串匹配,Z-算法、Manacher's算法用于求解最长回文子串。 10. **图论算法**:如Floyd-Warshall算法求解所有顶点间的最短路径,Dijkstra算法...
算法部分,书中可能会涵盖排序(如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等)、搜索(如线性搜索、二分搜索、深度优先搜索、广度优先搜索)、字符串处理(如最长公共子串、KMP算法)、图算法...
最长回文子串问题是找出给定字符串中最长的回文子串。可以通过动态规划等方法解决。 ### 七、数论 #### 7.1 中国剩余定理 中国剩余定理是一种用于解决同余方程组的理论,可以有效地求解多个同余方程的解。 #### ...
- **动态规划求解最长公共子序列**:找到两个字符串的最长不重复子串。 - **Trie树**:一种特殊的树结构,用于高效地存储和检索前缀相同的字符串。 5. **数据结构**: - **栈**:后进先出(LIFO)的数据结构,常...
字符串是一种特殊的线性数据结构,广泛应用于文本处理等领域。 **案例分析:Pku1961—Period** 题目描述:给定一个字符串,需要找出它的最小重复周期。此问题可以通过字符串匹配算法来解决,如KMP算法等。 **案例...
- 找出字符串数组中所有字符串的最长公共前缀。这是一个字符串处理的基础问题。 32. NextPermutation - 实现获取下一个排列的函数。这涉及到对排列的生成和排序算法的理解。 33. SearchInsertPosition - 给定一...
- height数组记录相邻后缀的最长公共前缀,有助于计算最长公共子串。 - 倍增算法和DC3算法可用于构建后缀数组,它们在时间和空间上都是线性的。 8. **统计字符串出现次数** - 利用C++中的`map`容器,可以高效地...