如何找到以1开头和结尾的所有子串?

时间:2015-02-04 19:55:40

标签: c++ algorithm

您将获得一个0和1的字符串,您必须找到字符串中以1开头和结尾的所有子字符串。

例如,给定0010110010,输出应为六个字符串:

101
1011
1011001
11
11001
1001

显然有一个O(N^2)解决方案,但我正在寻找一个复杂程度为O(N)的解决方案。有可能吗?

8 个答案:

答案 0 :(得分:3)

  

显然有一个O(N^2)解决方案,但我正在寻找一个复杂程度为O(N)的解决方案。有可能吗?

k为输入字符串中1的数量。然后有O(k^2)个这样的子串。枚举它们必须至少花费O(k^2)时间。如果k ~ N,则枚举它们必须花费O(N^2)时间。

获得O(N)解决方案的唯一方法是,我们添加ko(sqrt(N))的要求。一般情况下不能有O(N)解决方案,对k没有限制。

实际的O(k^2)解决方案很简单:

std::string input = ...;

std::vector<size_t> ones;
ones.reserve(input.size());

// O(N) find the 1s
for (size_t idx = 0; idx < input.size(); ++idx) {
    if (input[idx] == '1') {
        ones.push_back(idx);
    }
}

// O(k^2) walk the indices
for (size_t i = 0; i < ones.size(); ++i) {
    for (size_t j = i+1; j < ones.size(); ++j) {
        std::cout << input.substr(i, j - i + 1) << '\n';
    }
}

更新我们必须考虑子字符串的长度以及它们的数字。所有字符串的总长度为O(k * N),严格地大于先前声明的O(k^2)边界。因此,o(sqrt(N))上的k限制不足 - 我们实际上需要kO(1)才能产生O(N)解决方案。

答案 1 :(得分:2)

您可以通过以下步骤在O(n)中找到相同的内容:

    1.计算1的数量。
    2.让1的#为x,我们返回x(x-1)/2
    这非常简单地计算可能的1对的数量。
    代码本身可能值得自己尝试!
    编辑:
    如果您想要自己返回子字符串,则必须限制子字符串中1的数量,以便获得某种O(N)解决方案(或者真正O(x)其中{{ 1}}是你的#1&#39; ,因为在x时间复杂度的一般情况下,枚举它们本身不能减少。

答案 2 :(得分:0)

如果你只需要子串的数量而不是子串本身,你可以通过计算你遇到的1的数量的初始O(n)总和后计算对数来实现它。

答案 3 :(得分:0)

假设N应该是字符串中1的数量(或者至少与它成比例,假设每个字符的概率为1,这是合理的) :

如果你自己需要子串,那么它将是N(N-1)/2,这是二次的,所以它完全不可能比二次方更简单。

答案 4 :(得分:0)

import java.util.*;

public class DistictSubstrings {

public static void main(String args[]) {
// a hash set

Scanner in = new Scanner(System.in);
System.out.print("Enter The string");
String s = in.nextLine();
int L = s.length();
Set<String> hs = new HashSet<String>();
// add elements to the hash set
for (int i = 0; i < L; ++i) {


  for (int j = 0; j < L-i ; ++j) {
    if(s.charAt(j)=='1'&&s.charAt(j+i)=='1')
    {
    hs.add(s.substring(j, j+i + 1));
    }

 }
}
Iterator it=hs.iterator();
    System.out.println("the string starts and endswith 1");
    System.out.println(hs.size());
while(it.hasNext())
{
System.out.println(it.next()+" ");
}

答案 5 :(得分:0)

String s="1001010001";
for(int i=0;i<=s.length()-1;i++)
{
    for(int j=0;j<=s.length()-1;j++)
    {
        if(s.charAt(j)=='1' && s.charAt(i)=='1' && i<j)
        {
            System.out.println(s.substring(i,j+1));
        }               
    }
}

答案 6 :(得分:0)

以下python代码将帮助您查找以1开头和结尾的所有子字符串。

# -*- coding: utf-8 -*-
"""
Created on Tue Sep 26 14:25:14 2017

@author: Veeramani Natarajan
"""
# Python Implementation to find all substrings that start and end with 1

# Function to calculate the count of sub-strings 
def calcCount(mystring):
    cnt=-1
    index=0    
    while(index<len(mystring)):
        if(mystring[index]=='1'):
            cnt += 1
        index += 1
    return cnt


mystring="0010110010";
index=0;
overall_cnt=0

while(index<len(mystring)):
    if(mystring[index]=='1'):
        partcount=calcCount(mystring[index:len(mystring)])
        overall_cnt=overall_cnt+partcount
#        print("index is",index)
#        print("passed string",mystring[index:len(mystring)])
#        print("Count",partcount,"overall",overall_cnt)
    index=index+1
# print the overall sub strings count
print (overall_cnt)   

<强> 注意: 虽然这不是O(N)解决方案,但我相信它会帮助某人理解上述问题陈述的python实现。

答案 7 :(得分:0)

使用DP绝对可以实现O(n)解决方案。 我们采用一对数组,其中每个对中的第一个元素表示直到该索引的子字符串数,第二个元素表示从1 开始但不包括该索引的子字符串数。 (因此,如果该索引处的char为1,则第二个元素将不计算子字符串[1,1]) 我们就像在DP中一样简单地遍历数组并逐步构建解决方案,然后在循环结束之后,在数组的最后一个索引中,该对的第一个元素具有最终值。这是代码:

int getoneonestrings(const string &str)
{
    int n = str.length();
    if (n == 1)
    {
        return 0;
    }
    vector< pair<int, int> > dp(n, make_pair(0, 0));
    for (int i = 1; i < n; i++)
    {
        if (str[i] == '0')
        {
            dp[i].first = dp[i - 1].first;
        }
        else
        {
            dp[i].first = dp[i - 1].first + dp[i - 1].second +
                (str[i - 1] == '1' ? 1 : 0);
        }
        dp[i].second = dp[i - 1].second + (str[i - 1] == '1' ? 1 : 0);
    }
    return dp[n - 1].first;
}