【问题标题】:Need help optimizing a program that finds all possible substrings需要帮助优化查找所有可能子字符串的程序
【发布时间】:2012-02-01 21:02:05
【问题描述】:

我必须从一堆用户输入字符串中找到所有可能的唯一子字符串。这组子字符串必须按字母顺序排序,没有任何重复元素,并且该组必须按数字可查询。这是一些示例输入和输出:

输入:

3 // This is the user's desired number of strings
abc // So the user inputs 3 strings
abd
def
2 // This is the user's desired number of queries
7 // So the user inputs 2 queries
2

输出:

// From the alphabetically sorted group of unique substrings,
bd // This is the 7th substring 
ab // And this is the 2nd substring

这是我的实现:

#include <map>
#include <iostream>
using namespace std;

int main() {
    int number_of_strings;
    int number_of_queries;
    int counter;
    string current_string;
    string current_substr;
    map<string, string> substrings;
    map<int, string> numbered_substrings;
    int i;
    int j;
    int k;

    // input step
    cin >> number_of_strings;
    string strings[number_of_strings];
    for (i = 0; i < number_of_strings; ++i)
            cin >> strings[i];
    cin >> number_of_queries;
    int queries[number_of_queries];
    for (i = 0; i < number_of_queries; ++i)
            cin >> queries[i];

    // for each string in 'strings', I want to insert every possible
    // substring from that string into my 'substrings' map.
    for (i = 0; i < number_of_strings; ++i) {
            current_string = strings[i];
            for (j = 1; j <= current_string.length(); ++j) {
                    for (k = 0; k <= current_string.length()-j; ++k) {
                            current_substr = current_string.substr(k, j);
                            substrings[current_substr] = current_substr;
                    }
            }
    }

    // my 'substrings' container is now sorted alphabetically and does
    // not contain duplicate elements, because the container is a map.
    // but I want to make the map queryable by number, so I'm iterating
    // through 'substrings' and assigning each value to an int key.
    counter = 1;
    for (map<string,string>::iterator it = substrings.begin();
                    it != substrings.end(); ++it) {
            numbered_substrings[counter] = it->second;
            ++counter;
    }

    // output step
    for (i = 0; i < number_of_queries; ++i) {
            if (queries[i] > 0 && queries[i] <= numbered_substrings.size()) {
                    cout << numbered_substrings[queries[i]] << endl;
            } else {
                    cout << "INVALID" << endl;
            }
    }

    return 0;
}

我需要优化我的算法,但我不知道该怎么做。也许是因为我有第二个 for 循环来为每个子字符串分配新的 int 键。帮忙?

【问题讨论】:

  • 这个问题在这个网站上会更合适:codereview.stackexchange.com
  • 您可能会从使用 llvm 的 StringRef 类之类的东西中受益匪浅。它允许您在不分配新字符串的情况下制作子字符串和副本,只要源字符串保持不变。

标签: c++ string optimization substring


【解决方案1】:

查看后缀树。它通常在 O(n) 时间内运行:

这篇文章对我很有帮助: http://allisons.org/ll/AlgDS/Tree/Suffix/

【讨论】:

    【解决方案2】:

    小笔记:

    1. include <string>
    2. careful with those } else {; one day you'll have a lot of else if branches 
    and a lot of lines and you'll wonder where an if starts and where it ends
    3. careful with unsigned versus signed mismatching... again, one day it will 
    come back and bite (also, it's nice to compile without errors or warnings)
    4. don't try to define static arrays with a variable size
    5. nice with ++ i. not many know it has a slight performance boost 
    (maybe not noticeable with today's processors but still)
    

    虽然我同意在需要时使用适当的算法(比如冒泡排序、堆排序等进行排序、二叉搜索、二叉树等进行搜索),但有时我发现对当前代码进行优化是件好事。想象一下,有一个大项目并实施一些需要重写的东西……没有多少人愿意等你(更不用说所需的单元测试、胖测试,也许还有适合性测试)。至少我的看法。 [是的,我知道有些人会说,如果它如此复杂,那么它从一开始就写得很糟糕 - 但是,嘿,你不能与在你加入团队之前离开的程序员争论:P]

    但我同意,在需要时使用现有的东西是一个不错的选择。但回到正题。我用

    测试了它
    • 3、abc、def、ghi
    • 4、1、3、7、12

    我不能说你的是否比我的慢,反之亦然;也许添加可能 500 个输入(然后计算所有子项)的随机字符串生成器可能是一个更好的测试,但我在凌晨 2 点太懒了。至多,我的写作方式可能会对你有所帮助(至少在我看来,它看起来更简单,使用更少的循环和分配)。不是向量的粉丝,因为有轻微的开销,但我用它来满足您对动态查询的要求……显然,一个 const 的静态数组会更快。

    另外,虽然不是我的命名约定风格,但我决定使用您的名字,以便您可以更轻松地遵循代码。

    不管怎样,看看并告诉我你的想法:

    #include <map>
    #include <iostream>
    #include <string>           // you forgot to add this... trust me, it's important :)
    #include <vector>           // not a fan, but it's not that bad IF you want dynamic buffers
    #include <strstream>
    
    using namespace std;
    
    int main ()
    {
        unsigned int number_of_strings = 0;
        // string strings[number_of_strings];   // don't do this... you can't assign static arrays of a variable size
                                                // this just defaults to 0; you're telling the compiler 
    
        cin >> number_of_strings;
    
        map <string, string> substrings;
        string current_string, current_substr;
        unsigned int i, j, k;
    
        for (i = 0; i < number_of_strings; ++ i)
        {
            cin >> current_string;
            substrings[current_string] = current_string;
    
            for (j = 1; j <= current_string.length(); ++ j)
            {
                for (k = 0; k <= current_string.length() - j; ++ k)
                {
                    current_substr = current_string.substr(k, j);
                    substrings[current_substr] = current_substr;
                }
            }
        }
    
        vector <string> numbered_substrings;
    
        for (map <string, string>::iterator it = substrings.begin(); it != substrings.end(); ++ it)
            numbered_substrings.push_back(it->second);
    
        unsigned int number_of_queries = 0;
        unsigned int query = 0;
    
        cin >> number_of_queries;
        current_string.clear();
    
        for (i = 0; i < number_of_queries; ++ i)
        {
            cin >> query;
            -- query;
    
            if ((query >= 0) && (query < numbered_substrings.size()))
                current_string = current_string + numbered_substrings[query] + '\n';
                else
                    cout << "INVALID: " << query << '\n' << endl;
        }
    
        cout << current_string;
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-27
      • 2011-08-05
      • 2012-10-14
      • 2019-06-02
      相关资源
      最近更新 更多