我需要为最长的两个模式前缀/后缀匹配编码算法,其时间复杂度为O(n + m1 + m2),其中n是String的长度,m1,m2分别是pattern1和pattern2的长度
示例:如果字符串是“OBANTAO”而Pattern1是“BANANA”而Patten2是“SIESTA”,则答案是字符串的子字符串“BANTA”,其由BANANA的前缀BAN和SIESTA的后缀TA组成。
谷歌的结果是:“Rabin-karp string search algorithm”,“Knuth-morris-pratt algorithm”和“Boyer-moore string search algorithm”。
我能够理解以上3种算法,但问题是,它们都是基于“单一模式前缀/后缀匹配”。我无法为两个模式前缀/后缀匹配扩展它们。
示例算法或搜索它的链接对我开发程序非常有帮助。
答案 0 :(得分:2)
Knuth - Morris - Pratt可以直接修改,为干草堆字符串中的每个位置产生针头串的最长前缀的长度,其匹配结束于该位置。使用KMP以字符串形式为Pat1计算此信息,在反向(字符串)中反向(Pat2),然后遍历String中的每个位置,查找最大前缀/后缀长度。
String =“OBANTAO”和Pat1 =“BANANA”以及Pat2 =“SIESTA”的示例:
"BANANA" = Pat1 in String
O B A N T A O
^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | |
| | | | | | | 0 ("")
| | | | | | 0 ("")
| | | | | 0 ("")
| | | | 3 ("BAN")
| | | 2 ("BA")
| | 1 ("B")
| 0 ("")
0 ("")
"ATSEIS" = reverse(Pat2) in reverse(String)
O A T N A B O
^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | |
| | | | | | | 0 ("")
| | | | | | 0 ("")
| | | | | 1 ("A")
| | | | 0 ("")
| | | 2 ("AT")
| | 1 ("A")
| 0 ("")
0 ("")
反转第二个数组并按分数求和。
0 0 1 2 3 0 0 0
+ 0 0 1 0 2 1 0 0
-----------------
0 0 2 2 5 1 0 0
^
|
max (argument = "BAN" ++ reverse("AT"))
答案 1 :(得分:0)
我尝试用Java实现@David Eisenstat解决方案。 它在O(2n)时间和O(2(n + 1))辅助空间
String prefix = "BANANA";
String suffix = "SIESTA";
String input = "SABANANQS";
// Prepare Inputs
char[] prefixArray = prefix.toCharArray();
char[] suffixArray = suffix.toCharArray();
char[] inputArray = input.toCharArray();
int inputLength = inputArray.length;
int suffixLength = suffixArray.length;
int prefixLength = prefixArray.length;
// Auxiliary Spaces O(2(n+1))
int[] prefixIndexs = new int[inputLength+1];
int[] suffixIndexs = new int[inputLength+1];
int m = 0;
int n = 0;
// O(1)
for (int i = 0; i < inputLength; i++) {
if (inputArray[i] == prefixArray[m]){
m = m+1;
prefixIndexs[i+1] = m;
if (m == prefixLength) {
m = 0;
}
}else{
m = 0;
}
if (inputArray[inputLength-1-i] == suffixArray[suffixLength-1-n]){ // Reverse order or input and reverse oder of suffix
n = n +1;
suffixIndexs[i+1] = n;
if (n == suffixLength) {
n = 0;
}
}else{
n = 0;
}
}
int currmax =0;
int mIndex = 0; // prefix Index from start
int nIndex = 0; // suffix Index from End
//O(1) - Do Sum and find the max
for (int i = 0; i < (inputLength+1); i++) {
m = prefixIndexs[i];
n = suffixIndexs[inputLength-i];
if ( m != 0 && n != 0){ // if both prefix and suffix exists
if (m+n > currmax){
currmax = (m+n);
mIndex = m;
nIndex = n;
}
}
}
System.out.println("Input :"+input);
System.out.println("prefix :"+prefix);
System.out.println("suffix :"+suffix);
System.out.println("max :"+currmax);
System.out.println("mIndex :"+mIndex);
System.out.println("nIndex :"+nIndex);
System.out.println(prefix.substring(0,mIndex)+suffix.substring(suffix.length() - nIndex,suffix.length()));
不是将m和n重置为0,而是为每个实现KMP算法保留另一个数组,因为输入前缀和sufix没有重复的char序列我离开了它