题目:给定一个query和一个text,均由小写字母组成。要求在text中找出以同样的顺序连续出现在query中的最长连续字母序列的长度。例如, query为“acbac”,text为“acaccbabb”,那么text中的“cba”为最长的连续出现在query中的字母序列,因此,返回结果应该为其长度3。请注意程序效率。
我的思路是:假设短的那个字符串为s,求从下标i = 0 为起点的子串用KMP算法求其和长串的最大公共长度max,再求i=1时的max,一直到s.length - max。此后无需再继续,因为结果一定小于max。
代码如下:
publicclass FindMaxMatch {
int max= 0;// 最大已匹配长度
int index= -1;//已匹配字符串的起点
/**
* 获得匹配数组
*/
publicstaticint[] getNext(char[]pattern) {
if (null== pattern || pattern.length< 2) {
System.out.println("Error. no need for KMP");
returnnull;
}
int[] next =newint[pattern.length];
next[0]= -1;
next[1]= 0;
int k = 0;
int i = 1;
while (i < pattern.length - 1) {
if (pattern[i] == pattern[next[i]])
next[i]= next[next[i]];
if (pattern[i] == pattern[k]) {
next[i+ 1] = k + 1;
k++;
i++;
}elseif (k != 0)
k= 0;
else {
next[i+ 1] = 0;
i++;
}
}
if (pattern[i] == pattern[next[i]])
next[i]= next[next[i]];
return next;
}
publicvoid find(String pattern, String query) {
char[] qr = query.toCharArray();
int len = pattern.length();
//从i开始的每个子串的最大匹配长度i>len-max时无需再查找
for (inti = 0; i < len - max&&max < len; i++) {
char[] pt = pattern.substring(i).toCharArray();
int[] next =getNext(pt);
int k = 0;
int j = 0;
while (j < qr.length&& k < pt.length){
if (qr[j] == pt[k]) {
k++;
j++;
}else {
if (k >max){// 记录已匹配的最大长度
max = k ;
index = j - k;
}
k= next[k];
if (k == -1) {
k= 0;
j++;
}
}
}
if (k == pt.length){
max = k;
index = j - k;
}
}
}
publicstaticvoid main(String[] args) {
Strings = "sfdabcdaabcabead";
Stringq = "seedsdagdafasghfadshbagfsdnhbadghsrtjhnaasdgas fasfdabcdaabcaquery";
FindMaxMatch a = new FindMaxMatch();
a.find(s,q);
System.out.println(q.substring(a.index, a.max+ a.index) +" "
+a.index +" "+ a.max);
}
}
运行结果是:
sfdabcdaabc 51 11
使用前应判断长串和短串。我就不修改了。