Codeforces Round #438 (Div. 1 + Div. 2 combined) D. Huge Strings

15 篇文章 0 订阅
7 篇文章 0 订阅

D. Huge Strings

Problem Statement

    You are given n strings s1 ,  s2 , …,  sn consisting of characters 0 and 1. m operations are performed, on each of them you concatenate two existing strings into a new one. On the i-th operation the concatenation saisbi is saved into a new string sn+i (the operations are numbered starting from 1). After each operation you need to find the maximum positive integer k such that all possible strings consisting of 0 and 1 of length k (there are 2k such strings) are substrings of the new string. If there is no such k, print 0.

Input

    The first line contains single integer n (1 ≤ n ≤ 100) — the number of strings. The next n lines contain strings s1 ,  s2 , …,  sn (1 ≤  |si|  ≤ 100), one per line. The total length of strings is not greater than 100.
The next line contains single integer m (1 ≤ m ≤ 100) — the number of operations. m lines follow, each of them contains two integers ai and bi (1 ≤  ai ,  bi  ≤ n + i - 1) — the number of strings that are concatenated to form sn+i .

Output

    Print m lines, each should contain one integer — the answer to the question after the corresponding operation.

Examples

Example 1
    Input
        5
        01
        10
        101
        11111
        0
        3
        1 2
        6 5
        4 4
    Output
        1
        2
        0

Note

    On the first operation, a new string “0110” is created. For k = 1 the two possible binary strings of length k are “0” and “1”, they are substrings of the new string. For k = 2 and greater there exist strings of length k that do not appear in this string (for k = 2 such string is “00”). So the answer is 1.
    On the second operation the string “01100” is created. Now all strings of length k = 2 are present.
    On the third operation the string “1111111111” is created. There is no zero, so the answer is 0.

题意

    给你n个01串,之后给出m个操作,第i个操作把两个串接起来作为下一个串,标号为n+i,求每次操作接起来的这个串满足题意的最大的k是多少,满足题意就是长度为k的所有01串都为这个串的子串。

思路

    这题首先根据长度可以推断出,k最大为20(为了保险),这样,每个串只用存他开头20个字符和结尾20个字符来进行添加子串。对于原来给出的n个串,用一个set存下他所有长度小于20的子串,合并的时候只用将两个set合并就行了。之后判断的时候就判断长度为len时set的大小是不是( 1<<len )就行了。
P.S.注意这题不能直接存整个串,因为极限数据最大的串可以到 100299 的长度(好像),这样不MLE就怪了……(当时我就是存了整个串,就MLE并fst了…233)

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline void readInt(int &x) {
    x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    x*=f;
}
inline void readLong(ll &x) {
    x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    x*=f;
}
/*================Header Template==============*/
set<string> have[205][25];
string s,sst[205],sen[205];
int n,q,p1,p2,ans;
int main() {
    readInt(n);
    for(int i=1;i<=n;i++) {
        cin>>s;
        int l=s.length();
        for(int p=0;p<l;p++)
            for(int len=1;len<=min(l-p,22);len++)
                have[i][len].insert(s.substr(p,len));
        if(l>=22) {
            sst[i]=s.substr(0,22);
            sen[i]=s.substr(l-22,22);
        }
        else
            sst[i]=sen[i]=s;
    }
    readInt(q);
    for(int i=1;i<=q;i++) {
        cin>>p1>>p2;
        s=sen[p1]+sst[p2];
        int pos=sen[p1].length();
//      cout<<s<<endl;
        for(int l=1;l<=22;l++) {
            for(set<string>::iterator en=have[p1][l].begin();en!=have[p1][l].end();en++)
                have[n+i][l].insert(*en);
            for(set<string>::iterator en=have[p2][l].begin();en!=have[p2][l].end();en++)
                have[n+i][l].insert(*en);
        }
//      cout<<"!!!"<<pos<<" "<<endl;
        for(int p=pos-1;p>=max(0,pos-23);p--)
            for(int q=pos;q<min((int)s.length(),pos+22-(pos-p));q++) {
//              cout<<p<<" "<<q<<" "<<q-p+1<<" "<<s.substr(p,q-p+1)<<endl;
                have[n+i][q-p+1].insert(s.substr(p,q-p+1));
            }
        ans=0;
        for(int l=1;l<=22;l++)
            if(have[n+i][l].size()==(1<<l))
                ans=max(ans,l);
        printf("%d\n",ans);
        s=sst[p1]+sst[p2];
        sst[n+i]=s.substr(0,min(22,(int)s.length()));
        s=sen[p1]+sen[p2];
        sen[n+i]=s.substr(max((int)s.length()-22,0),min(22,(int)s.length()));
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值