记录编号 56708 评测结果 AAAAAAA
题目名称 [HAOI 2005]破译密文 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.002 s
提交时间 2013-04-02 17:16:37 内存使用 0.44 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int SIZEL=10001;//明文最大长度
int s1[SIZEL]={0},s2[SIZEL]={0};//存放两段处理过的密码
//规则是Hash:"第k个字符temp"=(temp-'a'+1)*100+k,这里k是从0开始算的
int pl;//明文的长度
const int SIZEH=3000;//Hash的最大长度
int father[SIZEH]={0};//每个点的节点
class ROOT{
public:
	int size;
	bool doom;//是否有了固定的值(0/1)不要吐槽翻译......
	int data;//0或1
};
ROOT root[SIZEH];
int findgra(int x){
	if(father[x]==-1) return x;
	else return findgra(father[x]);
}
bool merger(int a,int b){//a,b两个集合合并
	if(root[a].size<=root[b].size){//a合到b里
		father[a]=b;
		root[b].size+=root[a].size,root[a].size=0;
		if(root[b].doom){//b已经有定值了
			if(root[a].doom&&root[a].data!=root[b].data) return false;
		}
		else root[b].doom=root[a].doom,root[b].data=root[a].data;
	}
	else{//b合到a里
		father[b]=a;
		root[a].size+=root[b].size,root[b].size=0;
		if(root[a].doom){
			if(root[b].doom&&root[b].data!=root[a].data) return false;
		}
		else root[a].doom=root[b].doom,root[a].data=root[b].data;
	}
	return true;
}
bool match(void){
	int i,temp;
	for(i=0;i<pl;i++){
		if(s1[i]==0||s1[i]==1){//s1是0或1
			if(s2[i]==0||s2[i]==1) {if(s1[i]!=s2[i]) return false;}//确定的不同,失配
			else{
				temp=findgra(s2[i]);
				if(root[temp].doom) {if(root[temp].data!=s1[i]) return false;}
				else root[temp].doom=true,root[temp].data=s1[i];
			}
		}
		else{
			if(s2[i]==0||s2[i]==1){
				temp=findgra(s1[i]);
				if(root[temp].doom) {if(root[temp].data!=s2[i]) return false;}
				else root[temp].doom=true,root[temp].data=s2[i];
			}
			else{
				int gra1=findgra(s1[i]),gra2=findgra(s2[i]);
				if(gra1!=gra2){
					if(!merger(gra1,gra2)) return false;
				}
			}
		}
	}
	return true;
}
int n;//密码个数
int expsum[30]={0};//每个密码对应几个字符
bool used[SIZEH]={0};
bool read(void){
	string str1,str2;//两段原始文本
	cin>>str1>>str2;
	scanf("%d",&n);
	int i,j,p,temp;
	char ch;
	for(i=0;i<n;i++){
		cin>>ch,cin>>expsum[ch-'a'];
		temp=100*(ch-'a'+1);
		for(j=0;j<expsum[ch-'a'];j++){
			father[temp+j]=-1;
			root[temp+j].size=1;
			root[temp+j].doom=false;
			root[temp+j].data=-1;
		}
	}
	p=0;
	for(i=0;i<(int)str1.size();i++){
		if(str1[i]=='0'||str1[i]=='1') s1[p++]=str1[i]-'0';//0或1
		else{//把这个扩展出去
			temp=(str1[i]-'a'+1)*100;
			for(j=0;j<expsum[str1[i]-'a'];j++) s1[p++]=temp+j,used[temp+j]=true;
		}
	}
	pl=p;
	p=0;
	for(i=0;i<(int)str2.size();i++){
		if(str2[i]=='0'||str2[i]=='1') s2[p++]=str2[i]-'0';//0或1
		else{//把这个扩展出去
			temp=(str2[i]-'a'+1)*100;
			for(j=0;j<expsum[str2[i]-'a'];j++) s2[p++]=temp+j,used[temp+j]=true;
		}
	}
	if(p!=pl) return false;//两个长度不一样,失配
	return true;
}
void write(void){
	int sum=0;
	int i,j,temp;
	for(i=0;i<26;i++){
		if(expsum[i]>0){
			temp=100*(i+1);
			for(j=0;j<expsum[i];j++){
				if(used[temp+j]&&root[temp+j].size>0&&!root[temp+j].doom) sum++;
			}
		}
	}
	cout<<(1<<sum)<<endl;
}
int main(){
	freopen("encrypt.in","r",stdin);
	freopen("encrypt.out","w",stdout);
	bool flag;
	flag=read();//在这里读数据
	if(!flag) goto END;//失配了就直接0
	flag=match();
	if(!flag) goto END;
	write();
	return 0;
	END:;
	printf("0\n");
	return 0;
}