【问题标题】:Find most repeated sub strings in array查找数组中重复次数最多的子字符串
【发布时间】:2011-12-20 23:17:54
【问题描述】:

我有一个数组:

$myArray=array(

'hello my name is richard',
'hello my name is paul',
'hello my name is simon',
'hello it doesn\'t matter what my name is'

);

我需要找到最常重复的子字符串(最少 2 个单词),可能是数组格式,所以我的返回数组可能如下所示:

$return=array(

array('hello my', 3),
array('hello my name', 3),
array('hello my name is', 3),
array('my name', 4),
array('my name is', 4),
array('name is', 4),

);

所以我可以从这个数组数组中看到每个字符串在数组中的所有字符串中重复的频率。

只有这样的方法吗?..

function repeatedSubStrings($array){

    foreach($array as $string){
        $phrases=//Split each string into maximum number of sub strings
        foreach($phrases as $phrase){
            //Then count the $phrases that are in the strings
        }
    }

}

我尝试了类似于上述的解决方案,但速度太慢,每秒处理大约 1000 行,有人能做得更快吗?

【问题讨论】:

  • 您只需要重复次数最多的子字符串吗?还是您需要每个可能的子字符串的计数?这是两个截然不同的问题。
  • @BenLee:我真的只需要最常重复的子字符串,但如果可能的话,我想知道下一个是哪个。
  • @BenLee:最好的解决方案是运行速度最快的解决方案
  • @RichardLivingston:这个问题目前无法回答。要判断您的解决方案是否更快,我必须知道您的解决方案是什么。每秒 1000 行是非常相对的,这取决于您的硬件。删除伪代码,改为显示实际代码
  • 我同意 netcoder。执行取决于数组中字符串的大小以及字符串的数量。如果不知道这些行中的内容,每秒 1000 行并不是很有用。

标签: php arrays string


【解决方案1】:

解决这个问题的方法可能是

function getHighestRecurrence($strs){

  /*Storage for individual words*/
  $words = Array();

  /*Process multiple strings*/
  if(is_array($strs))
      foreach($strs as $str)
         $words = array_merge($words, explode(" ", $str));

 /*Prepare single string*/
  else
      $words = explode(" ",$strs);

  /*Array for word counters*/
  $index = Array();

  /*Aggregate word counters*/
  foreach($words as $word)

          /*Increment count or create if it doesn't exist*/
          (isset($index[$word]))? $index[$word]++ : $index[$word] = 1;


  /*Sort array hy highest value and */
  arsort($index);

  /*Return the word*/
  return key($index);
}

【讨论】:

  • 你应该使用$index = array();而不是$index;来初始化数组。
  • 我注意到我在阅读帖子时错过了这一点,谢谢。
  • 只有 cmets +1 的解决方案
  • @SOliver 如果我错了,请纠正我,但据我了解,您的解决方案仅提供最常出现的单词,而不是子字符串。最常出现的子字符串是“我的名字是”,它出现了 4 次。您的解决方案不是返回最常出现的单词吗?
【解决方案2】:

虽然这具有更高的运行时间,但我认为从实现的角度来看它更简单:

$substrings = array();

foreach ($myArray as $str)
{
    $subArr = explode(" ", $str);
    for ($i=0;$i<count($subArr);$i++)
    {
        $substring = "";
        for ($j=$i;$j<count($subArr);$j++)
        {
            if ($i==0 && ($j==count($subArr)-1))
                break;      
            $substring = trim($substring . " " . $subArr[$j]);
            if (str_word_count($substring, 0) > 1)
            {
                if (array_key_exists($substring, $substrings))
                    $substrings[$substring]++;
                else
                    $substrings[$substring] = 1;
            }
        }
    }   
}

arsort($substrings);
print_r($substrings);

【讨论】:

    【解决方案3】:

    我假设“子字符串”实际上是指“子字符串沿单词边界拆分”,因为这就是您的示例所显示的内容。

    在这种情况下,假设任何最大重复子字符串都可以(因为可能存在关联),如果您考虑一下,您始终可以只选择一个单词作为最大重复子字符串。对于任何短语“A B”,短语“A”和“B”单独出现的频率必须至少与“A B”一样频繁,因为它们都在每次“A B”出现时出现,并且它们可能在其他时间出现。因此,单个单词的计数必须至少与包含该单词的任何子字符串相关。

    因此,您只需将所有短语拆分为一组唯一的单词,然后只计算单词并返回计数最高的单词之一。这将比实际计算每个可能的子字符串运行得更快

    【讨论】:

    • 感谢您的回答,很有道理。如果子字符串的最小字长为 2,那么我是否必须将字符串拆分为所有可能的 2 字最小字符串?
    • @RichardLivingston,是的,我认为您必须拆分为所有 2 字字符串才能使用该比较。我想不出一个简单的方法来解决这个问题。
    • @richard,你为什么一直说“最低限度”?最好的 3 词短语永远不会比最好的 2 词短语更频繁地出现,他只是解释了原因。
    • @chris:我的意思是最小子字符串的长度为 2 个单词,而不是 Ben 建议的 1 个单词。我认为 Ben 理解我的意思并按我的预期回答,我需要知道子字符串的每个组合,而不是按单词边界分割。
    • @RichardLivingston,我认为克里斯的意思是没有理由说“子字符串的最小字长为 2”。您可以只说“子字符串的字长为 2”。 3 个词的短语无法击败它包含的 2 个词的短语,因此无需说“最少 2 个词”。你可以说“正好 2 个字”。
    【解决方案4】:

    这应该在 O(n) 时间内运行

    $twoWordPhrases = function($str) {
        $words = preg_split('#\s+#', $str, -1, PREG_SPLIT_NO_EMPTY);
        $phrases = array();
        foreach (range(0, count($words) - 2) as $offset) {
            $phrases[] = array_slice($words, $offset, 2);
        }
        return $phrases;
    };
    $frequencies = array();
    foreach ($myArray as $str) {
        $phrases = $twoWordPhrases($str);
        foreach ($phrases as $phrase) {
            $key = join('/', $phrase);
            if (!isset($frequencies[$key])) {
                $frequencies[$key] = 0;
            }
           $frequencies[$key]++;
        }
    }
    print_r($frequencies);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 2018-02-13
      • 1970-01-01
      • 1970-01-01
      • 2020-02-21
      • 2021-03-19
      相关资源
      最近更新 更多