在MySQL中进行排列搜索

时间:2018-11-01 11:24:19

标签: php mysql database search permutation

我需要帮助。
我有一个表,其中只有两列:ID和NAME以及这些数据:

public class PolindromeMyLogic {

static int polindromeCount = 0;

private static HashMap<Character, List<Integer>> findCharAndOccurance(
        char[] charArray) {
    HashMap<Character, List<Integer>> map = new HashMap<Character, List<Integer>>();
    for (int i = 0; i < charArray.length; i++) {
        char c = charArray[i];
        if (map.containsKey(c)) {
            List list = map.get(c);
            list.add(i);
        } else {
            List list = new ArrayList<Integer>();
            list.add(i);
            map.put(c, list);
        }
    }
    return map;
}

private static void countPolindromeByPositions(char[] charArray,
        HashMap<Character, List<Integer>> map) {
    map.forEach((character, list) -> {
        int n = list.size();
        if (n > 1) {
            for (int i = 0; i < n - 1; i++) {
                for (int j = i + 1; j < n; j++) {
                    if (list.get(i) + 1 == list.get(j)
                            || list.get(i) + 2 == list.get(j)) {
                        polindromeCount++;
                    } else {
                        char[] temp = new char[(list.get(j) - list.get(i))
                                + 1];
                        int jj = 0;
                        for (int ii = list.get(i); ii <= list
                                .get(j); ii++) {
                            temp[jj] = charArray[ii];
                            jj++;
                        }
                        if (isPolindrome(temp))
                            polindromeCount++;
                    }

                }
            }
        }
    });
}

private static boolean isPolindrome(char[] charArray) {
    int n = charArray.length;
    char[] temp = new char[n];
    int j = 0;
    for (int i = (n - 1); i >= 0; i--) {
        temp[j] = charArray[i];
        j++;
    }
    if (Arrays.equals(charArray, temp))
        return true;
    else
        return false;
}

public static void main(String[] args) {
    String str = "MADAM";
    char[] charArray = str.toCharArray();
    countPolindromeByPositions(charArray, findCharAndOccurance(charArray));
    System.out.println(polindromeCount);
}
}

我想显示例如如果用户搜索:HOME或OMEH或EMOH或HMEO等,则名称为HOME的行-单词HOME的所有排列。

我无法将所有这些排列保存到mysql并在此列中进行搜索,因为某些单词太大(9-10个字符),并且每9个字符超过40 MB。

2 个答案:

答案 0 :(得分:3)

解决此问题的一种方法是将排序后的字符集存储在数据库中的每个名称中作为附加列,然后对用户输入的字符串进行排序,然后再搜索。数据库具有

ID   NAME   CHARS
1    HOME   EHMO
2    GAME   AEGM
3    LINK   IKLN

然后在PHP中搜索时,您将执行以下操作:

$search = 'MEHO';                // user input = MEHO
$chars = str_split($search);
sort($chars);
$search = implode('', $chars);   // now contains EHMO
$sql = "SELECT ID, NAME FROM table1 WHERE CHARS = '$search'";
// perform query etc.

输出

ID   NAME
1    HOME

答案 1 :(得分:0)

这听起来像是一个“请帮我做功课”的问题。很难想象这适用于什么现实问题,也没有标准的解决方案。可以在这里寻求家庭作业的帮助,但是您应该说是这种情况。

  

每9个字符超过40 MB

您的数学运算有些奇怪,但实际上存储空间无法很好地扩展。在处理工作量方面,OTOH保留了存储量,可以作为解决方案很好地扩展。

您可以简单地强制执行动态查询:

 function mkqry($word)
 {
     $qry="SELECT * FROM yourtable WHERE 1 ";
     $last=strlen($word);
     for ($x=0; $x<$last; $x==) {
          $qry.=" AND word LIKE '%" . substr($word, $x, 1) . "%'";
     } 
     return $qry;
 }

但是,这将始终导致全表扫描(缓慢),并且无法正确处理字母在一个单词中出现两次的情况。

解决方案是使用索引功能,该功能与字符出现的顺序无关-非加密哈希。一个明显的选择是将字符异或,尽管这只会导致一个字符标识符的选择性不是很高。所以我建议简单地添加字符代码:

 function pos_ind_hash($word)
 {
     $sum=0;
     for ($x=0; $x<$last; $x==) {
         $sum+=ord(substr($word, $x));
     }
     return $sum;
 }

 function mkqry($word)
 {
     $qry="SELECT * FROM yourtable WHERE 1 ";
     $last=strlen($word);
     for ($x=0; $x<$last; $x==) {
          $qry.=" AND word LIKE '%" . substr($word, $x, 1) . "%'";
     }
     $qry.=" AND yourtable.hash=" .  pos_ind_hash($word);
     return $qry;
 }

请注意,此处的哈希机制并不能唯一地标识一个单词,但是它具有足够的特定性,可以将音量降低到索引(哈希)有效的程度。

相乘而不是相加会产生较少的冲突,但有更大的溢出风险(这会在实现之间产生歧义)。

但是散列和单个字符LIKE都只会减少潜在匹配项的数量。为了使查询具有确定的行为,您需要走得更远。您可以将包含字符串长度的属性添加到表(以及带有哈希的索引)中-这将更具选择性(即提高索引的有效性),但仍不确定。

对于一种确定的方法,您需要在查询中指定数据不包含您要查找的单词中不包含的字符。

错误的方法是添加一个循环,指定“ AND NOT LIKE ....”。

一种有效的方法是在查询中添加一个测试,以替换table属性中出现在要搜索的单词中的所有字母,从而得出长度为零的字符串。