Java 用Rabin-Karp算法寻找最长回文子串
从 15。最长回文子串。给定一个字符串s,查找最长的 是回文(或Watson-crick回文)的子字符串 解决方案:可以使用后缀树或 马纳彻算法。这里有一个简单的解决方案,通常在 线性时间。首先,我们描述如何找到所有回文 线性时间中长度正好为L的子字符串:使用Karp Rabin 迭代形成长度为L的每个子字符串的哈希(及其 相反),并进行比较。既然你不认识我,就不断地加倍努力 猜测L,直到你知道最佳长度在L和2L之间。然后 使用二进制搜索查找确切的长度 我不明白的是最后一部分 既然你不认识我,你就不断地加倍猜测我直到你 知道最佳长度在L和2L之间 我如何知道什么是“最佳”长度 旁白:最长回文子串的问题以前有人问过,但唯一有用的是,它也没有使用拉宾·卡普 编辑: 这是我根据收到的答案得出的代码Java 用Rabin-Karp算法寻找最长回文子串,java,string,algorithm,data-structures,rabin-karp,Java,String,Algorithm,Data Structures,Rabin Karp,从 15。最长回文子串。给定一个字符串s,查找最长的 是回文(或Watson-crick回文)的子字符串 解决方案:可以使用后缀树或 马纳彻算法。这里有一个简单的解决方案,通常在 线性时间。首先,我们描述如何找到所有回文 线性时间中长度正好为L的子字符串:使用Karp Rabin 迭代形成长度为L的每个子字符串的哈希(及其 相反),并进行比较。既然你不认识我,就不断地加倍努力 猜测L,直到你知道最佳长度在L和2L之间。然后 使用二进制搜索查找确切的长度 我不明白的是最后一部分 既然你不认识我,你
public static String longestPalindrome(String key) {
int r = 256;
long q = longRandomPrime();
boolean lastFound;
boolean found;
int l = 2;
do {
lastFound = indexOfPalindromeOfGivenLength(key, l, r, q) >= 0;
l *= 2;
found = indexOfPalindromeOfGivenLength(key, l, r, q) >= 0;
} while (l < key.length() && !(lastFound && !found));
int left = l / 2;
int right = l;
while (left <= right) {
System.out.printf("Searching for palindromes with length between: %d and %d%n", left, right);
int i = indexOfPalindromeOfGivenLength(key, left, r, q);
lastFound = i >= 0;
int j = indexOfPalindromeOfGivenLength(key, right, r, q);
found = j >= 0;
if (lastFound && found) return key.substring(j, j + right);
int x = left + (right - left) / 2;
if (!found) right = x;
else left = x;
}
return null;
}
private static int indexOfPalindromeOfGivenLength(String key, int l, int r, long q) {
System.out.printf("Searching for palindromes with length: %d%n", l);
for (int i = 0; i + l <= key.length(); i++) {
String s1 = key.substring(i, i + l);
long h1 = hash(s1, r, q);
long h2 = hash(new StringBuilder(s1).reverse().toString(), r, q);
if (h1 == h2) {
System.out.printf("Found palindrome: %s of length: %d%n", s1, s1.length());
return i;
}
}
System.out.printf("No palindromes of length %d exist%n", l);
return -1;
}
public静态字符串longestPalindrome(字符串键){
int r=256;
长q=长随机素数();
发现布尔值;
布尔发现;
int l=2;
做{
lastFound=IndexOfAlindromeofGivenLength(键,l,r,q)>=0;
l*=2;
found=IndexOfAlindromeofGivenLength(键,l,r,q)>=0;
}而(l=0;
if(lastFound&&found)返回key.substring(j,j+right);
int x=左+(右-左)/2;
如果(!found)right=x;
左=x;
}
返回null;
}
私有静态int IndexOfAlindromeofGivenLength(字符串键,int l,int r,long q){
System.out.printf(“搜索长度为:%d%n”,l)的回文);
对于(int i=0;i+l,当你到达l
时,你就知道最佳长度在l
和2L
之间
两个使用二进制搜索找到它。首先尝试L+ceil(L/2)
如果有此长度的回文子串,则对L+ceil(L/2)
和2L
执行相同的操作,同样,如果没有此长度的回文子串,则在[L,L+ceil(L/2)]中搜索
您搜索长度为L的回文子串,每次都加倍L,直到搜索失败。然后您知道真正的答案在失败长度和上次成功长度之间。您可以使用二进制搜索来找到它。@n.m.请参阅下面的注释或上面的代码。终止条件有意义吗?请参阅我的编辑。您可以吗我没有提到二进制搜索的终止条件,但经过一番思考后,我想到当两个边界都返回回文时,搜索应该终止。例如,使用字符串Forgekskeefor
,存在长度8
的回文(eeksskee
),以及长度10
(geekskeg
)。搜索终止并返回geekskeg
作为最长回文。