【问题标题】:Extracting a substring from a string of random letters从一串随机字母中提取子串
【发布时间】:2015-08-18 09:31:30
【问题描述】:

我有一个本质上是随机的字符串,例如“CBLBTTCCBB”。我的目标是计算字符串CTLBT 在字符串CBLBTTCCBB 中的出现次数。不允许重复用于检查的字母。例如,一旦形成CTLBT,下一次迭代的剩余随机字母将是BCCB

场景是我们有刮刮卡,用户可以在其中赢得字母来组成单词CTLBT。根据用户的记录,他赢得的字母在一个字符串CBLBTTCCBB中,根据购买刮刮卡从左到右排序。

我曾想过使用strpos,但这似乎不合适,因为它使用了较大字符串中子字符串的精确排列。

关于如何解决这个问题的任何想法?

谢谢!

注意: 问题不是 How to count the number of occurrences of a substring in a string? 的重复项,因为在给定链接中发布的解决方案是不同的。 substr_count 计算字符串中子字符串的出现次数,假设该字符串按照正确的顺序形成子字符串。

【问题讨论】:

  • @DevDonkey 到目前为止,我仍在收集我对此事的想法。我想过循环整个字符串,但我想它会效率低下。
  • @VladimirGilevich 尝试了 substr_count 但它没有考虑干草堆的随机性。我的目标是获取由随机字符串形成的目标字符串的出现。
  • @Jhn 所以你想检查CTLBTCBLBTTCCBB的每个订单组合中出现了多少次?
  • @Jhn 在答案中添加了一个变体:)

标签: php string


【解决方案1】:

然后你可以使用 preg_replace 代替 strpos:

function rand_substr_count($haystack, $needle)
{
    $result = $haystack;

    for($i=0; $i<strlen($needle); $i++) {
        $result = preg_replace('/'.$needle[$i].'/', '', $result, 1);
    }

    if (strlen($haystack) - strlen($result) == strlen($needle)) {
        return 1 + rand_substr_count($result, $needle);
    } else {
        return 0;
    }
}

echo rand_substr_count("CBLBTTCCBB", "CTLBT");

【讨论】:

  • OP 希望知道搜索出现了多少次(如果有人赢了两次或更多次)
  • @Tensibai 感谢您的注意! - 将代码移动到函数中 - 现在可以很容易地使用来获取计数。
  • 很好地使用递归函数 :) 请问为什么 preg_replace 而不是 str_replace 用于单个字母替换? (IIRC 它更快,但我可能错了)
  • str_replace() 将替换所有存在的字符,但使用 preg_replace() 我们只能替换第一个找到的字符。所以 - 只是为了这个细微差别preg_replace() 在这里更好。
  • 哇,确实,再次阅读文档,发现我忘记了 str_replace 中的 $count 是占位符而不是限制。对不起;)
【解决方案2】:

如果我理解正确,我会这样做(用打印显示结果):

<?
# The string to test
$string="CBLBTTCCBBTLTCC";
# The winning word
$word="CTLBT";

# Get the letters from the word to use them as unique array keys
$letters=array_unique(str_split($word));
print("Letters needed are:\n".print_r($letters,1)."\n");

# Initialize the work array
$match=array("count" => array(),"length"=> array());
# Iterate over the keys to build the array with the number of time the letter is occuring
foreach ($letters as $letter) {
  $match['length'][$letter] = substr_count($word,$letter); #Number of time this letter appears in the winning word
  $match['count'][$letter] = floor(substr_count($string,$letter) / $match['length'][$letter]); # count the letter (will be 0 if none present) and divide by the number of time it should appear, floor it so we have integer

}
print("Count of each letter divided by their appearance times:\n".print_r($match['count'],1)."\n");

# Get the minimum of all letter to know the number of times we can make the winning word
$wins = min($match['count']);
# And print the result
print("Wins: $wins\n");
?>

输出:

Letters needed are:
Array
(
    [0] => C
    [1] => T
    [2] => L
    [3] => B
)

Count of each letter divided by their appearance times:
Array
(
    [C] => 5
    [T] => 2
    [L] => 2
    [B] => 4
)

Wins: 2

由于您希望不分顺序地计算组合,字母的最小计数将是用户获胜的次数,如果没有一个字母,则为0。

我让你把它转换成一个函数并清理你不希望的打印行;)

【讨论】:

  • 谢谢@Tensibai!我将尝试实施您建议的更好的选择
  • @jhn 告诉我,我现在时间很紧,我稍后会有更多时间改进它
  • @Jhn 答案改进了,如果有不清楚的地方请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
  • 2021-04-14
  • 1970-01-01
相关资源
最近更新 更多