在具有k个查询的二进制字符串中查找具有全1的最长子字符串的长度

时间:2017-12-02 11:57:15

标签: algorithm data-structures

给定一个由0和/或1组成的大小为n的字符串。您必须执行 k 查询,并且可能有两种类型的查询。

  1. “1”(不带引号):打印长度最长的子串,全部为“1”。
  2. “2 X”(不带引号):其中X是1到n之间的整数。在此查询中,您将第X个位置的字符更改为“1”(第i个位置的字符可能已经是' 1' )
  3. 输入格式:

    • 第一行输入包含n和k,其中n是字符串长度,k是查询数。
    • 下一行包含一个0和/或1的长度为n的字符串。
    • 下一个k行中的每一行都包含任何一种类型的查询(即1或2)。

    输出格式:对于类型1的每个查询,在新行中打印子阵列的最大大小        全是1。

         Example Input:                        Example Output:
         5 7                                   0
         00000                                 1
         1                                     1
         2 3                                   3
         1                                     
         2 5
         1
         2 4
         1
    

    我的解决方案:O(k * n)(如果大多数类型1的查询)

     if(type==1){
            int count=0, ans=0;
            for(int i=0;i<str.size();i++){  //longest len substring
                if(str[i]=='1'){
                    count++;
                }else{
                   ans=max(ans,count);
                   count=0;
                }
            }
    
            printf("%d\n",ans);
     }else{
            int xth;
            scanf("%d",&xth);
            str[xth-1]='1';   //update
     }
    

    我无法找到一个有效的解决方案,因为'type 1'查询只有我能想到的解决方案是每次迭代字符串并连续保持一个“count”变量并最终更新“ans” “当ith str成为'0'时变量。

    我正在考虑使用分段树但不知道该怎么做。根据需要,良好的解决方案应该是O(k * log(n))(在log(n)时间内执行“type1”查询)

2 个答案:

答案 0 :(得分:1)

这可以使用Disjoint sets datastructure解决,其中每个数字都是空集。

当&#34; 0&#34;将索引i翻转为&#34; 0&#34;。检查是否item[i-1] == 1,如果是,请将集{i}加入包含i-1的集合。与item[i+1]类似。

由于你永远不会断开&#34; sets&#34;,你可以缓存&#34;最长的子串&#34;当你计算新的集合时(通过检查你刚创建的新子集现在是否最长,如果是,则存储相关长度)

对于&#34; 1&#34;此解决方案的时间复杂度为O(1)。键入操作,O(alpha(n))用于&#34; 2&#34;类型操作(其中alpha:N->N是反ackerman,这是sublogarithmic)。

这可以为O(k*alpha(n))个查询提供k最差案例效果。

所以,举个例子:

5 7
Create 5 sets: {1} {2} {3} {4} {5}
 00000
 1
Nothing cached, answer is 0
 2 3
2 and 4 are zeros, so don't connect with anything. Cache biggest length 1 ({3})
 1
1 is cached
 2 5
Flip 5. Don't connect with anything.
 1
1 is cached
 2 4
Flip 4. Join({3},{4}) Since both are 1. Join({3,4},{5}) similarly. Cache 3 (since it's the new size of the set contianing 4 is bigger than 1).
 1
3 is cached.

答案 1 :(得分:0)

绝对完美@amit基于他的解释,这里是c ++实现
这里的等级是维持最大构成1,因此您可以在O(1)时间内返回查询1,因为SOl在更新时始终具有最大值1

#include <bits/stdc++.h>
using namespace std;
typedef struct subset
{
    int parent;
    int rank;
}subset;
int find(subset subsets[], int i)
{
    if (subsets[i].parent != i)
        subsets[i].parent = find(subsets, subsets[i].parent);
    return subsets[i].parent;
}
void Union(subset subsets[], int x, int y)
{
    int xroot = find(subsets, x);
    int yroot = find(subsets, y);
    if(subsets[xroot].rank < subsets[yroot].rank)
    {
        subsets[xroot].parent = yroot;
        subsets[yroot].rank += subsets[xroot].rank;
    }
    else if (subsets[xroot].rank > subsets[yroot].rank)
    {
        subsets[yroot].parent = xroot;
        subsets[xroot].rank += subsets[yroot].rank;
    }
    else
    {
        subsets[yroot].parent = xroot;
        subsets[xroot].rank+=subsets[yroot].rank;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,k,i,q,t,sol=0;
    cin >> n >> k;
    string s;
    cin >> s;
    cin.ignore();
    subset subsets[n];
    for(i=0;i<n;i++)
    {
        subsets[i].parent = i;
        subsets[i].rank = 0;
        if(s[i]=='1')
        {
            subsets[i].rank = 1;
        }
    }
    for(t=0;t<n;t++)
    {
        if(s[t] == '1' && t!=0 && t!=n-1)
        {
            if(s[t-1] == '1')
            {
                int x = find(subsets,t-1);
                int y = find(subsets,t);
                if(x!=y)
                {

                    Union(subsets,t-1,t);
                    sol = max(sol,max(subsets[x].rank,subsets[y].rank));
                    sol = max(sol,subsets[t].rank);
                }
            }
            if(s[t+1] == '1')
            {
                int x = find(subsets,t+1);
                int y = find(subsets,t);
                if(x!=y)
                {
                    Union(subsets,t+1,t);
                    sol = max(sol,max(subsets[x].rank,subsets[y].rank));
                    sol = max(sol,subsets[t].rank);
                }
            }
        }
        if(s[t] == '1' && t==0 )
        {
            if(s[t+1] == '1')
            {
                int x = find(subsets,t+1);
                int y = find(subsets,t);
                if(x!=y)
                {

                    Union(subsets,t+1,t);
                    sol = max(sol,max(subsets[x].rank,subsets[y].rank));
                    sol = max(sol,subsets[t].rank);
                }
            }
        }
        if(s[t] == '1' && t==n-1)
        {
            if(s[t-1] == '1')
            {
                int x = find(subsets,t-1);
                int y = find(subsets,t);
                if(x!=y)
                {

                    Union(subsets,t-1,t);
                    sol = max(sol,max(subsets[x].rank,subsets[y].rank));
                    sol = max(sol,subsets[t].rank);
                }
            }
        }
        sol = max(sol,subsets[t].rank);
    }
    for(i=0;i<k;i++)
    {
        cin >> q;
        if(q==1)
        {
            cout << sol << endl;
        }
        else
        {
            cin >> t;
            t--;
            if(s[t] == '0' && t!=0 && t!=n-1)
            {
                s[t] = '1';
                subsets[t].rank = 1;
                if(s[t-1] == '1')
                {
                    int x = find(subsets,t-1);
                    int y = find(subsets,t);
                    if(x!=y)
                    {

                        Union(subsets,t-1,t);
                        sol = max(sol,max(subsets[x].rank,subsets[y].rank));
                        sol = max(sol,subsets[t].rank);
                    }
                }
                if(s[t+1] == '1')
                {
                    int x = find(subsets,t+1);
                    int y = find(subsets,t);
                    if(x!=y)
                    {

                        Union(subsets,t+1,t);
                        sol = max(sol,max(subsets[x].rank,subsets[y].rank));
                        sol = max(sol,subsets[t].rank); 
                    }
                    //Union(subsets,t+1,t);
                }
            }
            if(s[t] == '0' && t==0 )
            {
                s[t] = '1';
                subsets[t].rank = 1;
                if(s[t+1] == '1')
                {
                    int x = find(subsets,t+1);
                    int y = find(subsets,t);
                    if(x!=y)
                    {
                        Union(subsets,t+1,t);
                        sol = max(sol,max(subsets[x].rank,subsets[y].rank));
                        sol = max(sol,subsets[t].rank);
                    }
                }
            }
            if(s[t] == '0' && t==n-1)
            {
                s[t] = '1';
                subsets[t].rank = 1;
                if(s[t-1] == '1')
                {
                    int x = find(subsets,t-1);
                    int y = find(subsets,t);
                    if(x!=y)
                    {
                        Union(subsets,t-1,t);
                        sol = max(sol,max(subsets[x].rank,subsets[y].rank));
                        sol = max(sol,subsets[t].rank);
                    }
                }
            }
            sol = max(sol,subsets[t].rank);
        }
    }
}