洛谷p1032 字串变换 (bfs)

题目概述

链接:洛谷P1032
字符串的子串(必须连续与子序列不同)有至多六种变化规则,若在10步(包含10步)以内能将A变换为B,则输出最少的变换步数;否则输出"NO ANSWER!"

题目分析

关键词“最少的变换步数”,那么首选的是广度优先遍历,从字符串A开始,遍历每一种变化规则,然后生成新的字符串入队列。同时要有一个map映射,确定以前出现过的字符串不能再次出现
题目难度:普及+/提高

AC代码

#include
using namespace std;
map<string,int> mp; //从前出现过的字符串不能再次出现(广度搜索树,第一次搜到的一定是最短路径) 
string chg[6][2];   //六种变化规则的字符串 
string a,b; //初始字符串 与 目标字符串
int len[10];   // 每一个字符串的长度 
int ans;  //记录最后结果 
int k = 0; //变换规则的数量 
struct node{
	string str;
	int step;
};
queue<node>qu;
void bfs()
{
	node now;
	now.step = 0;
	now.str = a;
	qu.push(now);    //字符串a,入队列
	while(!qu.empty())
	{ 
		node next = qu.front(); qu.pop();
		if(mp[next.str]==1) continue;  //如果以前出现过,则跳过,对广度优先搜索树进行剪枝!
		if(next.str == b)     //如果已经达到目标,则退出遍历过程
			{
				ans = next.step;
				break;	
			}	
		mp[next.str] = 1;  //进行标记
		
		int now_len = next.str.length();
		for(int i=0;i<k;i++) //k种变化规则 
		{
			for(int j=0;j<now_len;j++)   //从第一个字符到最后一共字符
			{
				if(len[i]+j>now_len) break;  //如果新字符串超限,则退出循环
				string nt= next.str.substr(j,len[i]);	
				if(nt == chg[i][0])    
				{
					node temp;        //变化字符,采用string库中的 substr取子串的操作
					temp.str =  next.str.substr(0,j)+chg[i][1]+next.str.substr(j+len[i],now_len-j-len[i]);
					temp.step=next.step+1;
					qu.push(temp);    //新字符串入队列
				}
			}
		}
	}
	if(ans<=10&&ans!=0)   //默认如果不发生变换就相等的话,也是输出没有答案! 
		{                 //还有就是永远也无法达到目标字符串b,即ans没有变化,0 
			cout<<ans;	
		}	
	else cout<<"NO ANSWER!";
}
int main()
{
	cin>>a>>b;
	int i = 0;	
	while(cin>>chg[i][0]>>chg[i][1])
	{
		i++;
	} 
	k=i;//记录输入的规则个数 
	for(int j=0;j<i;j++)
		len[j] = chg[j][0].length();
	bfs();
}
**这里重点用的取子串的函数是string库里的 substr(a,b)注意参数a指的是起始index,b指的是截取子串的长度!

你可能感兴趣的:(搜索)