Codeforces Round #438 D. Huge Strings

Description

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.

解题报告

这题对于合并的两个串的操作,新串对两个合并的串连边,由于每一次长度最多翻一倍,也就是最长为 \(2^{100}\) ,所以 \(k\) 长度也不超过100,所以可以分治处理,那么新串就可以只存新串的长度为100的部分,也就是说 左边部分的后k个和右边部分的前k个需要单独算贡献,内部的贡献直接分治处理,枚举 \(k\),然后直接哈希字符串判断出现次数,并记录串的个数是否等于 \(2^k\) 即可

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=205;
string s[N][2];int len[N],n,ls[N],rs[N],m,tot=0;
map<string,int>re;bool vis[N];
void dfs(int x,int k){
   if(vis[x])return ;vis[x]=true;
   if(!rs[x]){
      for(int i=0;i+k<=len[x];i++){
         string w=s[x][0].substr(i,k);
         if(!re[w]){
            re[w]++;tot++;
         }
      }
      return ;
   }
   string S=s[ls[x]][1]+s[rs[x]][0];
   int li=S.size();
   for(int i=0;i+k<=li;i++){
      string w=S.substr(i,k);
      if(!re[w]){
         re[w]++;tot++;
      }
   }
   dfs(ls[x],k);dfs(rs[x],k);
}
bool check(int k,int x){
   memset(vis,0,sizeof(vis));re.clear();tot=0;
   dfs(x,k);
   if(tot==(1<<k))return true;
   return false;
}
void work()
{
   scanf("%d",&n);
   for(int i=1;i<=n;i++){
      cin>>s[i][0];
      s[i][1]=s[i][0];
      ls[i]=rs[i]=0;
      len[i]=s[i][0].size();
   }
   scanf("%d",&m);
   for(int i=n+1;i<=n+m;i++){
      scanf("%d%d",&ls[i],&rs[i]);
      s[i][0]=s[ls[i]][0];
      if(len[ls[i]]<=100)s[i][0]=s[i][0]+s[rs[i]][0];
      if(s[i][0].size()>=100)s[i][0]=s[i][0].substr(0,100);
      s[i][1]=s[ls[i]][1];
      if(len[rs[i]]<=100)s[i][1]=s[i][1]+s[rs[i]][1];
      if(s[i][1].size()>=100)s[i][1]=s[i][1].substr(s[i][1].size()-100,100);
      int k=1;
      for(k=1;k<=100;k++){
         if(!check(k,i))break;
      }
      printf("%d\n",k-1);
   }
}

int main()
{
	work();
	return 0;
}

posted @ 2017-10-06 08:01  PIPIBoss  阅读(231)  评论(0编辑  收藏  举报