字串变换

字串变换

https://www.luogu.com.cn/problem/P1032

前言:

NOIp提高组2002的一道字符串+广搜题,还是有难度的

因为你首先得通过题意分析出这是一道广搜,然后还要在编程中避开所有的坑(手动狗头)

题目简述:

给定初始字符串A和目标串B,以及不多于6个的变换规则

要求求出将A变成B的最少步骤数,如果步骤数在10步以内(包含10步)就输出答案,否则输出“NO ANSWER!”


解题思路:

(1)首先分析一下为什么是广搜题,题意变换一下:

给定初始位置和目标位置,以及不多于6个的移动方向(变换规则),要求求出从初始到目标的最少步数

这不就是明摆的广搜嘛!?

(2)分析出了广搜,那最基础的代码思路也就成型了:

①首先将输入的规则存入两个数组中,一个存变化前一个存变化后

以A为出发点开始广搜,对于每一个队首字符串,我们开双层循环枚举它的每一个位置,再枚举每一种变换规则

③然后进入处理变换的函数change中,首先判断改变后的字符串是否合法,合法的话就进行改变并返回压入队尾

(3)再来讲一下change函数,判断是否合法主要是两个条件

①改变后的字符串长度大于队首字符串的长度,不合法

②改变后的字符和规则不相等,不合法

注意:将以上的思路转换为代码之后,提交上去,你就会发现,你要么T了3、5要么RE了3、5,反正只有60pts。所以就有了如下的第四步优化操作:

(4)设置一个map<string,int> 数组,每处理了一个字符串就标记一下(其实就相当于普通广搜标记当前位置是否走过),这样判重以后,你就A掉了这个题


代码Code:

PS:主程序中用/**/括起来的代码是用来检查样例能不能对用的

#include <bits/stdc++.h>
using namespace std;
int n,ans;
string A,B,gz[1001],gzs[1001];
map<string,int> shan; //shan这个map数组用来剪枝判重

struct node {
	string word;
	int st;
} q[100001];

inline string change(string tmp,int x,int y) { //改变字符串 
	string sum="";
	if(gz[y].length()+x>tmp.length()) return sum; //判断是否合法 
	for(register int i=0;i<gz[y].length();i++) {
		if(tmp[x+i]!=gz[y][i]) return sum;
	}
	sum=tmp.substr(0,x); //substr,string的函数,下面会补充介绍 
	sum+=gzs[y];
	sum+=tmp.substr(x+gz[y].length());
	return sum;
}

inline void bfs(string a) {
	int front=1,tail=1;
	q[front].word=a;
	q[front].st=0;
	while(front<=tail) {
		for(register int i=0;i<q[front].word.length();i++) { //枚举当前对头字符串的每一个位置 
			for(register int j=0;j<n;j++) { //再枚举每一种转换手段 
				string now=change(q[front].word,i,j);
				if(now!=""&&shan[now]!=1) { //如果变换后的字符串合法且没有处理过,就入队 
					tail++;  
					q[tail].word=now;
					q[tail].st=q[front].st+1; //累加步数 
					shan[now]=1;
					if(now==B) { //如果到达了B就输出步数 
						ans=q[tail].st;
						return ;
					}
				}
			}
		}
		front++;
	}
}

int main() {
	cin>>A>>B;
/*	n=3;
	for(register int i=0;i<n;i++) {
		cin>>gz[i]>>gzs[i]; 
	}*/
	while(cin>>gz[n]>>gzs[n]) n++; //一直输入规则 
	bfs(A); //以字符串A为起点开始广搜 
	if(ans>10||ans==0) puts("NO ANSWER!"); 
	else printf("%d",ans);
	return 0;
}

补充一下:

substr(pos,len)返回从pos号位开始、长度为len的子串,时间复杂度为O(len)

吐槽一下:直接输出“NO ANSWER!”可以得到20pts....没加判重的BFS一般是40-60pts不等


原文地址:https://www.cnblogs.com/Eleven-Qian-Shan/p/13099530.html