是否有一种快速算法可以在两个strings
中找到最大公共子字符串,还是一个NPComplete问题?
在PHP中,我可以在大海捞针中找到针:
<?php
if (strstr("there is a needle in a haystack", "needle")) {
echo "found<br>\n";
}
?>
我想我可以在strings
之一的循环中执行此操作,但这将非常昂贵!特别是因为我的应用是搜索电子邮件数据库并查找垃圾邮件(即同一个人发送的类似电子邮件)。
有没有人有他们可以丢弃的PHP代码?
答案 0 :(得分:10)
答案 1 :(得分:7)
特别是因为我的申请是搜索电子邮件数据库并查找垃圾邮件(即同一个人发送的类似电子邮件)。
我认为您应该关注贝叶斯垃圾邮件推理算法,而不一定是最常见的子串。
http://www.devshed.com/c/a/PHP/Implement-Bayesian-inference-using-PHP-Part-1/
答案 2 :(得分:5)
我刚写了一个函数,找到str2中存在于str2
中的最长子字符串public static function getLongestMatchingSubstring($str1, $str2)
{
$len_1 = strlen($str1);
$longest = '';
for($i = 0; $i < $len_1; $i++){
for($j = $len_1 - $i; $j > 0; $j--){
$sub = substr($str1, $i, $j);
if (strpos($str2, $sub) !== false && strlen($sub) > strlen($longest)){
$longest = $sub;
break;
}
}
}
return $longest;
}
答案 3 :(得分:3)
此后我发现了a relevant wikipedia article。它不是NP完全问题,可以使用动态编程算法在O(mn)时间内完成。
在PHP中,我发现similar_text函数非常有用。这是一个代码示例,用于检索一系列文本电子邮件并循环遍历它们,并找到彼此90%相似的电子邮件。 注意:这样的内容不可扩展:
<?php
// Gather all messages by a user into two identical associative arrays
$getMsgsRes = mysql_query(SELECT * FROM email_messages WHERE from = '$someUserID');
while($msgInfo = mysql_fetch_assoc($getMsgsRes))
{
$msgsInfo1[] = $msgInfo;
$msgsInfo2[] = $msgInfo;
}
// Loop over msgs and compare each one to every other
foreach ($msgsInfo1 as $msg1)
foreach ($msgsInfo2 as $msg2)
similar_text($msg1['msgTxt'],$msg2['msgTxt'],$similarity_pst);
if ($similarity_pst > 90)
echo "{$msg1['msgID']} is ${similarity_pst}% to {$msg2['msgID']}\n";
?>
答案 4 :(得分:3)
这个派对的后期,但是这里有一种方法可以找到字符串数组中最大的公共子字符串:
示例:
$array = array(
'PTT757LP4',
'PTT757A',
'PCT757B',
'PCT757LP4EV'
);
echo longest_common_substring($array); // => T757
功能:
function longest_common_substring($words) {
$words = array_map('strtolower', array_map('trim', $words));
$sort_by_strlen = create_function('$a, $b', 'if (strlen($a) == strlen($b)) { return strcmp($a, $b); } return (strlen($a) < strlen($b)) ? -1 : 1;');
usort($words, $sort_by_strlen);
// We have to assume that each string has something in common with the first
// string (post sort), we just need to figure out what the longest common
// string is. If any string DOES NOT have something in common with the first
// string, return false.
$longest_common_substring = array();
$shortest_string = str_split(array_shift($words));
while (sizeof($shortest_string)) {
array_unshift($longest_common_substring, '');
foreach ($shortest_string as $ci => $char) {
foreach ($words as $wi => $word) {
if (!strstr($word, $longest_common_substring[0] . $char)) {
// No match
break 2;
} // if
} // foreach
// we found the current char in each word, so add it to the first longest_common_substring element,
// then start checking again using the next char as well
$longest_common_substring[0].= $char;
} // foreach
// We've finished looping through the entire shortest_string.
// Remove the first char and start all over. Do this until there are no more
// chars to search on.
array_shift($shortest_string);
}
// If we made it here then we've run through everything
usort($longest_common_substring, $sort_by_strlen);
return array_pop($longest_common_substring);
}
我在博客上写了一点:
答案 5 :(得分:1)
请查看Wikibooks上的Algorithm implementation/Strings/Longest common substring。我还没有测试过PHP实现,但它似乎与维基百科页面上的通用算法相匹配。