如何在字符串中找到最长的连续子字符串?

时间:2012-11-21 09:00:06

标签: string algorithm

例如,有一个给定的字符串,由1s0s组成:

s = "00000000001111111111100001111111110000";
  • 获取s中最长1s子字符串计数的有效方法是什么? (11
  • 在s中获取最长0s子串的有效方法是什么? (10

我很欣赏这个问题可以从算法的角度来回答。

3 个答案:

答案 0 :(得分:0)

我认为最直接的方法是在记录所有0和所有1子字符串的最大长度时遍历位串。这是其他人建议的O (n)复杂度。

如果您能够负担某种数据并行计算,您可能需要查看并行模式,如here所述。具体来说,请看parallel reduction。我认为如果您能够负担其中一种方法,可以在O (log n)时间内实施此问题。

我正在考虑对此问题进行并行缩减:

  1. 在缩减的第一级,每个线程将处理8位字符串的块(取决于您拥有的线程数和字符串的长度)并生成摘要比特串如:0 -> x, 1 -> y, 0 -> z, ....

  2. 在下一个级别,每个线程将其中两个摘要合并为一个,任何可能的联接都将在此阶段执行(基本上,如果上一个摘要以0结束({{1} })并且下一个摘要以10)开头,然后最后一个条目和两个摘要的第一个条目可以合并为一个。)

  3. 在顶层,只有一个结构带有位串的总结,你必须逐步找出最大的序列(但这次它们都是摘要形式,所以它应该更快)。或者,您可以使每个摘要结构跟踪大型10子字符串,这将使您无需遍历最终结构。

  4. 我想这种方法只在非常有限的范围内才有意义,但是因为你似乎非常热衷于比1更好......

答案 1 :(得分:0)

好的,这是我提出的一个解决方案,我不确定这是否是无错误的。如果您发现错误或建议更好的方法,请纠正我。如果您同意此解决方案,请投票。谢谢!

#include <iostream>

using namespace std;

int main(){

    int s[] = {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0};
    int length = sizeof(s) / sizeof(s[0]);

    int one_start = 0;
    int one_n = 0;
    int max_one_n = 0;

    int zero_start = 0;
    int zero_n = 0;
    int max_zero_n = 0;

    for(int i=0; i<length; i++){
        // Calculate 1s
        if(one_start==0 && s[i]==1){
            one_start = 1;
            one_n++;
        }
        else if(one_start==1 && s[i]==1){
            one_n++;
        }
        else if(one_start==1 && s[i]==0){
            one_start = 0;
            if(one_n > max_one_n){
                max_one_n = one_n;
            }
            one_n = 0;      // Reset 
        }

        // Calculate 0s
        if(zero_start==0 && s[i]==0){
            zero_start = 1;
            zero_n++;
        }
        else if(zero_start==1 && s[i]==0){
            zero_n++;
        }
        else if(one_start==1 && s[i]==1){
            zero_start = 0;
            if(zero_n > max_zero_n){
                max_zero_n = zero_n;
            }
            zero_n = 0;     // Reset 
        }
    }

    if(one_n > max_one_n){
        max_one_n = one_n;
    }
    if(zero_n > max_zero_n){
        max_zero_n = zero_n;
    }

    cout << "max_one_n: " << max_one_n << endl;
    cout << "max_zero_n: " << max_zero_n << endl;

    return 0;
}

答案 2 :(得分:0)

最坏的情况总是O(n),你总能找到强制算法检查每一位的输入。

但你可能会得到平均值稍微好一些(更简单地说,只扫描0或1,而不是两者),因为你可以跳过当前找到的最长序列的长度并向后扫描。至少这将减少O(n)的常数因子,但至少对于随机输入,更多项目也意味着更长的序列,因此更长和更长的跳过。但与O(n)的区别不会太大......