繁体   English   中英

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

[英]How to find all substrings that start and end with 1?

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

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

101
1011
1011001
11
11001
1001

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

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

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

获得O(N)解的唯一方法是,如果我们添加ko(sqrt(N)) 在一般情况下,不存在对k无限制的O(N)解。

实际的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) 因此,绑定到ko(sqrt(N))是不够的-我们实际上需要kO(1)才能产生O(N)解。

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

    1.计算1的数量。
    2.假设1的#为x ,我们返回x(x-1)/2
这很简单地计算了可能的1对的数量。
代码本身可能值得尝试!
编辑:
如果要自己返回子字符串,则必须限制子字符串中1的数量,以便获得某种O(N)(或实际上是O(x) ,其中x是您的1的#)在一般情况下,不能从O(N^2)时间复杂度上减少它本身的大小。

如果只需要子字符串的数目,而不是子字符串本身,则可以通过对遇到的1的数目进行初始O(n)加和后计算对的数目来实现

假设N应该是字符串中1 s的数量(或至少与之成正比,假设每个字符的恒定概率为1 ,则这是合理的):

如果您需要子字符串本身,则将是N(N-1)/2 ,它是二次方的,因此完全不可能没有二次方那么复杂。

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()+" ");
}
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));
        }               
    }
}

以下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实现。

使用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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM