问题描述
:设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前缀串的数量。
分享到:
相关推荐
通过计算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等,这些...
- **特定算法题目的解决**:如判断字符串的旋转,求最长无重复字符子串等。 这本书通过详尽的算法题目和知识点,提供了一个完整的面试准备方案,不仅涉及了传统的数据结构和算法,还包括了一些高级数据结构与算法,...
- **最长公共前缀**:在后缀树中,从根节点到任何内部节点的路径代表了一个共享前缀,最长的路径即为最长公共前缀。 - **模式计数**:计算一个模式在字符串中出现的次数。 - **基因序列比对**:在生物信息学中,后缀...
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`容器,可以高效地...
- 实现KMP算法的关键是构建next数组或nextval数组,用以存储前缀和后缀相等的最长子串长度,从而指导后续的匹配过程。 综上所述,这些面试题目涵盖了从基本的人际交往能力到专业技能的多个层面,旨在全面评估应聘者...