Codeforces868D Huge Strings

45 篇文章 0 订阅
40 篇文章 0 订阅

标签:记忆化搜索,模拟,位运算

You are given n stringss1, s2, ..., sn consisting of characters 0 and 1.m operations areperformed, on each of them you concatenate two existing strings into a new one.On thei-th operation the concatenationsaisbiis saved into a new stringsn +i(the operations are numbered starting from 1). After each operation you need tofind the maximum positive integerk such that all possible stringsconsisting of 0 and 1 of length k (there are 2k suchstrings) are substrings of the new string. If there is no suchk, print 0.

Input

The first line contains single integern(1 ≤ n ≤ 100) — thenumber of strings. The nextn lines contain stringss1, s2, ..., sn (1 ≤ |si| ≤ 100), one per line. The total length of strings is not greater than 100.

The next line contains single integerm(1 ≤ m ≤ 100) — thenumber of operations.m lines follow, each of them contains two integersai abdbi (1 ≤ ai, bi ≤ n + i - 1) — the number of strings that areconcatenated to formsn +i.

Output

Print m lines, each should containone integer — the answer to the question after the correspondingoperation.

Example

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. Fork = 1 the two possiblebinary strings of lengthk are "0" and "1", they aresubstrings of the new string. Fork = 2 and greater there exist strings of lengthk that do notappear in this string (fork = 2 such string is "00"). So the answer is 1.

On the second operation the string "01100"is created. Now all strings of lengthk = 2 are present.

On the third operation the string "1111111111"is created. There is no zero, so the answer is 0.

 

题意:给定n个01字符串,进行m次操作,每次将Sa,Sb,两个字符串合并成为新串Sn+i

求:对于每个新和成的字符串,存在数字k,满足长度为k的01字符全排列都存在于新和成的字符串的子串中,询问k的最大值

分析:

直接模拟就好了,注意求出的每个ans,一定要存储下来,记忆化使用,01字符全排列可以使用位运算加速,不会TLE

代码中取头尾各500,防止MLE

我们合并两个字符串的时候,对答案产生贡献的部分就是两者中间衔接部分

所以我们可以只记录每个字符串的头和尾作为特征来更新答案

对于这种做法答案的正确性,可以有递推式ans[n+i]=max(max(ans[l],ans[r]),work(n+i))保证,满足答案递增(是部分递增,不是全局递增),貌似可以有严谨(xuan xue)的数学证明但是本蒟蒻不会啊,大家有数据也可以hack。


Code

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define mem(x,num) memset(x,num,sizeof x)
using namespace std;
const int maxn=206;
int ans[maxn],n,m,l,r;
string s[maxn];

int work(int x){
	rep(i,1,10)
	    rep(j,0,(1<<i)-1){
	    	string t;
	    	rep(k,0,i-1){
	    		if(j&(1<<k))t+='1';
	    		else t+='0';
	    	}
	    	if(s[x].find(t)==-1)return i-1;
	    }
}
int main()
{
	scanf("%d",&n);
	rep(i,1,n)cin>>s[i];
	scanf("%d",&m);
	rep(i,1,m){
		scanf("%d%d",&l,&r);
		s[n+i]=s[l]+s[r];
		if(s[n+i].length()>1000)s[n+i]=s[n+i].substr(0,500)+s[n+i].substr(s[n+i].length()-500,500);
		ans[n+i]=max(max(ans[l],ans[r]),work(n+i));
		cout<<ans[n+i]<<endl;
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值