uva:310 - L--system(字符串处理+ bfs)

310 - L--system


题目大意:给出替换的a, b字符串,用来替换遇到的a, b,和起始的字符串和目标字符串,问能否构成形如:(x目标字符产y)这样的字符串;其中x, y可以为空。


解题思路:刚开始想用bfs每次替换一个a,或是b,然后储存起来,但是这样的话最后的数组变得非常的大;后来借鉴了别人的思路:他是把原字符串里面长度小于等于目标字符串长度的子串分离出来,做标志,用来判断是否找到目标字符串,或是这个子字符串是否已经重复判断。这样的话又不会漏掉别的情况,也不会重复判断,而且这样数组的大小就可以控制了,因为给出的四个字符串长度不超过15,这样所有的字串的情况也不超过 1<<15 种,而且就算每个替换的字符串长度为15,然后需要替换的原字符产长度最长为15, 这样所有的都替换了15 * 15 = 225; 里面有个临时数组开300就足够了。还有因为只有a, b,和空,所以可以用1,2,0来代替,这样产生的值,int型就可以接受,所以可以直接开个数组来判重。注意这里要区分a和空的状态,例如ba,和b 是不一样的。


#include<stdio.h>
#include<string.h>
#include<string>

const int N = 300;
const int M = 1 << 16;
char s1[20], s2[20], start[20], target[20], q[M][20], tmp[N];
int end, vis[M];

int hash(char *p){
	
	int sum = 0;
//	printf("%s %d\n", p, strlen(p));
	for(int i = 0; i < strlen(p); i++){
//		if(p[i] - 'a')
//		sum += 1 << i;
		sum = sum *2 + p[i] - 'a' + 1;
//		printf("%d ", sum);
	}
//	printf("%d\n", sum);
	return sum % M;
}
int  bfs(){
	
	memset(vis, 0, sizeof(vis));
	int front = 0, rear = 0;
	int k , i, j;
	for(i = 0; start[i]; i++){

		for(j = i, k = 0; start[j] && target[k]; j++)
			q[rear][k++] = start[j];
		q[rear][k] = '\0';
		int n = hash(q[rear]);
		
//		printf("%d\n", n);
		if(n == end)
				return 1;
		if(!vis[n]){
			
			vis[n] = 1;
			rear++;	
		}
	}
	while (front < rear){
		for( i = 0, k = 0; q[front][i]; i++){
			
			if (q[front][i] == 'a'){
				
				for(j = 0; s1[j]; j++)
					tmp[k++] = s1[j];
			}else if (q[front][i] == 'b'){
				
				for(j = 0; s2[j]; j++)
					tmp[k++] = s2[j];

			}
		}	
		tmp[k] = '\0';
		for( i = 0; tmp[i]; i++){
			for(j = i, k = 0; tmp[j] && target[k]; j++){
				
				q[rear][k++] = tmp[j];
			}
			q[rear][k] = '\0';
			int n = hash(q[rear]);
			
			if(n == end)
				return 1;
			if(vis[n] != 1){
				
				vis[n] = 1;
				rear++;
			}
		}
		front++;
	}
	return 0;
}

int main(){

	while(scanf("%s", s1) != EOF){

		scanf("%s%s%s", s2, start, target);
		memset(q, 0, sizeof(q));	
		end = hash(target);
		int flag = bfs();
		if(flag)
			printf("YES\n");
		else
			printf("NO\n");
	}
 	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值