列表

详情


NC20260. [SCOI2008]劣质编码

描述

一个编码方案把每个字符对应到一个01串。例如{1,1010,01,10101}就是一个编码方案,它把四个字符(假设 它们为a,b,c,d)分别对应到串1、1010,01,10101。
字符串的编码为各字符编码的连接。例如,在刚才的编码方 案中,字符串cac的编码为01101,dcb的编码为10101011010。 
进一步分析发现,刚才的编码是相当劣质的,因为 字符串ba, acc和d的编码都是10101。
对于一个编码方案,你的任务是找出三个不同的字符串,使得它们的编码全相同。换句话说,找一个01编码串,使得它至少有三种解码方式。如果有多组解,这个编码串应当尽量短。

输入描述

第一行包含一个整数n,即符号的个数。
以下n行每行为一个长度不超过50的01串(可能为空串),即各符号的 编码。

输出描述

仅一行,包含一个整数,即最短编码的长度。如果无解,输出-1。

示例1

输入:

4
1
1010
01
10101

输出:

5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 187ms, 内存消耗: 26660K, 提交时间: 2020-09-23 14:35:01

#include<bits/stdc++.h>
#define LL long long
#define vi vector<int>
using namespace std;
int n,id[35][55],totl,dfn;
string str[35];
vi s,t;map<vi,int>mp;
queue<vi>q;
int main(){
	scanf("%d",&n);
	for(int i=1,l;i<=n;i++){
		cin>>str[i];l=str[i].size();totl+=l;
		if(!l){puts("0");return 0;}
		for(int j=0;j<l;j++)id[i][j]=dfn++;
	}
	s.resize(totl);t.resize(totl);
	for(int i=1;i<=n;i++)s[id[i][0]]=1;
	mp[s]=0;q.push(s);
	while(!q.empty()){
		vi u=q.front();q.pop();int ns=mp[u];
		for(char ch='0';ch<='1';ch++){
			for(int i=0;i<totl;i++)t[i]=0;
			int ed=0;
			for(int i=1,l;i<=n;i++){
				l=str[i].size();
				for(int j=0;j<l;j++)if(str[i][j]==ch){
					if(j==l-1)ed+=u[id[i][j]];else t[id[i][j+1]]=u[id[i][j]];
				}
			}
			if(ed>=3){printf("%d\n",ns+1);return 0;}
			for(int i=1;i<=n;i++)t[id[i][0]]=ed;
			if(!mp.count(t))mp[t]=ns+1,q.push(t);
		}
	}
	puts("-1");
	return 0;
}

上一题