编写Java代码以查找仅包含来自以下字母的9个字母的字符串: acegikmnoprstuvy
字符串散列产生的地方: 932246728227799
如果散列函数由以下伪代码定义:
hash (String s) {
h = 7
letters = "acegikmnoprstuvy"
for(i = 0; i < s.length; i++) {
h = (h * 37 + letters.indexOf(s[i]))
}
return h
}
例如,如果我们试图找到生成字符串690336378753的7字母字符串,答案就是&#34;报告&#34;。
答案 0 :(得分:3)
哈希基本上对从基数为37到基数10的字符串进行编码。为了反转哈希,我们将从基数10转换为基数37.当我们处理它时,不妨查找字符。
public class Hashcode {
static final String ALPHABET = "acegikmnoprstuvy";
public static long hash(String s) {
long h = 7;
for (int i=0; i<s.length(); i++) {
h = (h * 37 + ALPHABET.indexOf(s.charAt(i)));
}
return h;
}
public static String unhash(long n) {
String result = "";
while (n>7) {
result = ALPHABET.charAt((int)(n%37)) + result;
n = n/37;
}
if (n != 7) {
System.err.println("Error, hash parity incorrect.");
System.exit(1);
}
return result;
}
public static void main(String[] args) {
System.out.println(hash("reports"));
System.out.println(unhash(690336378753L));
System.out.println(unhash(932246728227799L));
System.out.println(hash("mymitsapp"));
}
}
答案 1 :(得分:3)
以数学方式查看函数的作用。
当你进入for循环时,你从h = 7开始。 for循环遍历单词中的字母。每次迭代都会更新h:h = h * 37 + next_letter
所以尝试选择一个词,ex&#34; ADD&#34;。
循环1:h = 7 * 37 + "A"
循环2:h = (7 * 37 + "A") * 37 + "D"
→7 * 37^2 + "A" * 37 + "D"
循环3:h = (7 * 37^2 + "A" * 37 + "D") * 37 + D
→7 * 37^3 + "A" * 37^2 + "D" * 37 + "D"
所以你的哈希将是7 * 37^3 + "A" * 37^2 + "D" * 37 + "D"
在实际情况下,字母会转换为索引编号,因为最大索引小于37,您只能得到一个可能的解决方案。将哈希值重写为7 * 37^3 + "A" * 37^2 + "D" * 37 + "D"
也会显示它可以作为7 "A" "D" "D"
在基数37中写得清楚。
长答案简短:只需将其转换为基础37并删除前导7.
答案 2 :(得分:1)
word(hashcode,len) = let w: hash(w) = hashcode
或者有更具体的功能:
word(hashcode,len) = let w: for(i = 0 , i < len , 1){w[len-i-1] * 37^i} + 909732178565539 - hashcode = 0
所以现在我们有了一个等式,下一步是解决它:
将(hashcode-909732178565539)
从十进制转换为基数37.在带有基数37的数字中,每个数字将代表您单词中的一个字符。现在您需要做的就是将单个数字转换为您的字符。
答案 3 :(得分:1)
这是用php编写的解决方案。您需要做的就是在基数37中取消给定的整数。
function unhash($h) {
$letters = "acegikmnoprstuvy";
//new string return
$s='';
while ($h>7){
//hold
$pos = fmod($h, 37);
$s = $letters[$pos].$s;
$h = ($h-$pos) / 37 ;
}
return $s;
}