【洛谷P1032】字串变换

【洛谷P1032】字串变换_第1张图片
卡了比较久的一道bfs…同时学到很多新姿势还旧债
思路就是不断根据变换规则,将变换后的字串加入队列,累加step计数,如果step>10就直接输出NO ANSWER。
在变换字串这一步卡了很久,直到了解到string里居然还有这么牛逼的replace()find()函数字符串欠债多
入队的字串需要判重否则字串变换上可能会陷入奇妙的无限循环 ,这个用STL的set解决
另外一个需要注意的坑点是原串A里可能出现多个相同的子串A1,如果继续用find()的话就只能定位到排在最前面的子串A1,后面的就无法处理到,导致节点扩展不完全

//Matsuri
#include
using namespace std;
string a,b,ori[10],tran[10];
int cnt=0,ans=0;
typedef struct{string str;int step;}node;
node sp,ep;
queue<node>q;
set<string>m;
int searchforsub(const string &chief, const string &subtran)
{
	static int pos=chief.find(subtran,0); //静态变量,初始化过程仅执行一次 
	static string formersub=""; //静态变量,初始化过程仅执行一次 
	//处理多个相同子串的情况
	if (subtran==formersub)
	{
		pos=chief.find(subtran,pos+1); //从上一次找到的字串位置的下一位起再找一次字串 
		return pos;
	}
	else
	{
		formersub=subtran;
		pos=chief.find(subtran,0);
		return pos;
	}
}
void bfs()
{
	node cur,nex; string tcur; int pos;
	q.push(sp); m.insert(sp.str);
	while(!q.empty())
	{
		cur=q.front();q.pop();
		tcur=cur.str;
		if (cur.step>10) // 超过10步就直接把ans设成大于10的数,结束bfs 
		{
			ans=11;
			break;
		}
		if (tcur==ep.str)
		{
			ans=cur.step;
			break;	
		}
		for (int i=0;i<cnt;i++)
		{
			pos=searchforsub(tcur,ori[i]);
			while (pos!=string::npos)
			{
				string tmp=tcur; 
				// tcur.replace()会直接修改tcur,导致bfs扩展节点出错,必须再用个tmp存然后再操作 
				nex.str=tmp.replace(pos,ori[i].size(),tran[i]);
				nex.step=cur.step+1;
				if (m.count(nex.str)==0)
				{
					m.insert(nex.str);
					q.push(nex);
				}	
				pos=searchforsub(tcur,ori[i]);
			}		
		}
	}
}
int main()
{
	cin>>a>>b;
	while(cin>>ori[cnt]>>tran[cnt]){cnt++;}
	sp.str=a;sp.step=0;
	ep.str=b;
	bfs();
	if (ans>10 || ans==0) puts("NO ANSWER!");
	else printf("%d\n",ans);
	return 0;
}

简单总结一下replace(),find()的用法:
replace():三种常用用法

#include
string s;
//用法一:用str替换指定字符串从起始位置pos开始长度为len的字符 
//s.replace(进行替换的起始位置,长度,替换子串)
s.replace (size_t pos, size_t len, const string& str); 
//用法二: 用str替换 迭代器起始位置 和 结束位置 的字符 
//s.replace(进行替换的起始位置,进行替换的结束位置,替换子串)
s.replace (const_iterator i1, const_iterator i2, const string& str);
//用法三: 用substr的指定子串(给定起始位置和长度)替换从指定位置上的字符串 
//s.replace(进行替换的起始位置,长度,替换子串,替换子串的起始位置,替换子串的长度)
s.replace (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen); 

find()
s.find(“xxx”),在s字符串里找称作“xxx”的子串,若找到则会返回该子串第一个字符的下标,否则返回string::npos

s.find (const string& str, size_t pos = 0) const;  
//s.find("..."),只写一个参数则默认从下标0开始寻找子串 
//s.find("...",pos),从下标pos开始寻找子串

你可能感兴趣的:(BFS,C++)