【问题标题】:Optimise a Python/ C++ algorithm优化 Python/C++ 算法
【发布时间】:2021-06-29 13:00:11
【问题描述】:

我正在参加一个竞争性的编程竞赛,并面临一个问题,在四个测试用例中,我的答案在 3 中是正确的,但在第 4 时超过了时间限制。

我试图通过将我的代码从 python 转换为 cpp 来获得更好的结果(我知道时间复杂度保持不变,但值得一试:)

以下是问题:

如果字符串包含至少 K 个连续字符“*”,则称该字符串使用强语言。 给你一个长度为 N 的字符串 S。判断它是否使用强语言。

输入

  • 输入的第一行包含一个整数 T,表示测试用例的数量。 T 测试用例的描述如下。
  • 每个测试用例的第一行包含两个以空格分隔的整数 N 和 K。
  • 第二行包含一个长度为 N 的字符串 S。

输出

如果字符串包含强语言,则打印包含字符串“YES”的单行,如果不包含则打印“NO”

我的python方法:

for _ in range(int(input())):
    k = int(input().split()[1])
    s = input()
    s2 = "".join(["*"]*k)
    if len(s.split(s2))>1:
        print("YES")
    else:
        print("NO")

我转换的 Cpp 代码(自己转换的

#include <iostream>
#include<string>

using namespace std;

int main() {
    // your code goes here
    int t;
    std::cin >> t;
    for (int i = 0; i < t; i++) {
        /* code */
        int n,k;
        std::cin >> n >> k;
        string str;
        cin >> str;
        string str2(k,'*');

        size_t found = str.find(str2);
        if (found != string::npos){
            std::cout << "YES" << std::endl;
        } else {
            std::cout << "NO" << std::endl;
        }
    }
    return 0;
}

请指导我如何降低时间复杂度?

其他方法:“使用 find() 函数代替 split 或使用 for 循环”

编辑: 示例输入:

2
5 1
abd
5 2
*i**j

输出:

NO
YES

【问题讨论】:

  • 你能发布一个示例输入文件吗?
  • 编辑@sedavidw
  • 我不知道 std::string::find 在幕后做了什么,但是如果您正在寻找连续的 N 个星号,您可以检查每个第 N 个字符是否都是一个星号,这将捕获所有这样的延伸,还有更短的。如果你成功了,数一数之前和之后有多少个星号。这将节省您的时间,但前提是 N 很大。
  • 是的!我找到了这个问题。在这个问题上,你必须比 O(n) 做得更好。也许从 GFG 或 cp-algorithms.com 阅读其他字符串匹配算法。它可能会帮助你...
  • 你也可以去研究教授建议的算法,然后遇到Boyer-Moore algorithm,它的工作原理类似:它根据可能的匹配来推进要寻找的地方。我想如果你的搜索字符串是统一的,你会得到类似于我建议的东西。

标签: python c++ algorithm optimization


【解决方案1】:

您发布的界限表明 Python 中的线性时间是可以的。您可以简单地跟踪您连续看到了多少个星号。

T = int(input())
for _ in range(T):
    n, k = map(int, input())
    s = input()
    count, ans = 0, False
    for c in s:
        if c == "*":
            count += 1
        else:
            count = 0
        ans = ans or count >= k
    if ans:
        print("NO")
    else:
        print("YES")

我也可以告诉你你为什么要 TLE'ing。考虑n = 1e6k = 5e5s 是第一个k-1 字符是星号的字符串的情况。您拥有的 find 方法将检查每个位置以匹配您创建的str2。这将花费 O(n^2) 时间,为您提供 TLE。

【讨论】:

  • 我稍微修改了您的代码并应用了@MOehm 的一些建议,结果成功了,非常感谢:)
  • @trincot 每次调用“find”都是线性的,因为它必须检查每个连续的位置。 find 不知道或先验地检查所有字符是否相同,因此在每个位置调用 find 直到匹配。
  • @JerryHalisberry,这是对find 工作方式的假设。你能提供证据吗?
  • @trincot 这是标准。您可以自己查看 cppreference:cplusplus.com/reference/string/string/find
  • 该引用未指定算法。
猜你喜欢
  • 2015-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-21
  • 2023-03-09
  • 1970-01-01
  • 2019-02-24
  • 1970-01-01
相关资源
最近更新 更多