[Codeforces Round #438][Codeforces 868D. Huge Strings]

题目链接:868D - Huge Strings

题目大意:有(n)个字符串,(m)次操作,每次操作把两个字符串拼在一起,并询问这个新串的价值。定义一个新串的价值(k)为:最大的(k),使得这个新串包含所有长度为(k)的01串(这样的字符串有(2^k)个)

题解:首先来证明对于任何的串,这个(k)的值不会超过9

   若(k=10),由所有字符串的长度总和不超过100,因此在初始的(n)个串里,互不相同的长度为(k)的子串不超过100个。又由于每次连接最多能产生9个新的长度为(k)的子串(即横跨两个字符串之间的子串),因此互不相同的子串个数最多为(9 cdot100+100<2^k),故(k<10)

   接下来就只需要记录每个字符串的前缀,后缀以及长度为(k)的子串有哪些就好了。

#include<bits/stdc++.h>
using namespace std;
#define N 101
int n,m,a,b;
struct rua
{
    string st,ed;
    set<int>has[10];
    bool check(int k)
      {
      for(int i=0;i<(1<<k);i++)
        if(!has[k].count(i))return false;
      return true;
      }
    int ans()
      {
      for(int k=9;k>0;k--)
        if(check(k))return k;
      return 0;
      }
    rua connect(rua nxt)
      {
      rua res=nxt;
      res.st=st;
      if(st.size()<9)
        res.st=st+nxt.st.substr(0,min(nxt.st.size(),9-st.size()));
      int cpy_len=min(ed.size(),9-nxt.ed.size());
      if(nxt.ed.size()<9)
        res.ed=ed.substr(ed.size()-cpy_len,cpy_len)+nxt.ed;
      for(int k=1;k<=9;k++)
        for(auto i:has[k])res.has[k].insert(i);
      string tmp=ed+nxt.st;
      int len=tmp.size();
      for(int i=0;i<len;i++)
        {
        int value=0;
        for(int d=0;d<9 && i+d<len;d++)
          value=value*2+tmp[i+d]-'0',
          res.has[d+1].insert(value);
        }
      return res;
      }
}f[2*N];
string s;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      {
      cin>>s;
      int len=s.size();
      for(int j=0;j<len;j++)
        {
        int value=0;
        for(int d=0;d<9 && j+d<len;d++)
          value=value*2+s[j+d]-'0',
          f[i].has[d+1].insert(value);
        }
      int cpy_len=min(9,len);
      f[i].st=s.substr(0,cpy_len);
      f[i].ed=s.substr(len-cpy_len,cpy_len);
      }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
      {
      scanf("%d%d",&a,&b);
      f[n+i]=f[a].connect(f[b]);
      printf("%d
",f[n+i].ans());
      }
}
View Code
原文地址:https://www.cnblogs.com/DeaphetS/p/9693580.html