题目大意是给定原始字符串A和目标字符串B
并提供一些子串的提供方案,如果串中存在某个子串a,则可以将其替换为子串b。
求解的问题是至少经过多少次子串替换可以让A变换到B,如果替换次数超过10次或者不能变换到B,则表示问题无解。
例如输入:
abcd xyz
abc xu
ud y
y yz
输出为3
表示abcd经过3次子串替换后可以得到xyz。
这个题很显然是一个广搜题,因为要求最少次数。问题的关键在于这个字符串的替换让人觉得有点不舒服,那么采用STL中的String中的方法就可以较为简便地完成。
string中的substr方法可以有效地完成字符串的截取任务,find方法可以便捷地查询字符串中包含某个子串的位置。
搜索的过程中注意剪枝,不然会超时。用一个map,记录每次替换后的得到的字符串对应的总操作次数。当经过某次替换后出现map中存在的字符串的时候,就是重复,这个时候需要剪枝。
#include<string>
#include <vector>
#include <map>
#include <queue>
#include <iostream>
using namespace std;
struct node
{
string str;
int step;
};
vector<pair<string, string>> replaceTable;
map<string, int> searchTable;
string from, to;
void bfs()
{
node start;
start.str = from;
start.step = 0;
queue<node> nodeQue;
nodeQue.push(start);
while (!nodeQue.empty())
{
node cur = nodeQue.front();
nodeQue.pop();
if (cur.step > 10 )
{
cout << "NO ANSWER!" << endl;
return;
}
if (cur.str == to)
{
cout << cur.step << endl;;
return;
}
for (auto replacePair : replaceTable)
{
int pos = cur.str.find(replacePair.first);
while (pos!=cur.str.npos)
{
string newStr = cur.str.substr(0, pos);
newStr += replacePair.second;
newStr += cur.str.substr(pos+replacePair.first.size());
if (!searchTable[newStr] || searchTable[newStr] > cur.step + 1)
{
node newNode;
newNode.step = cur.step + 1;
newNode.str = newStr;
searchTable[newStr] = cur.step + 1;
nodeQue.push(newNode);
}
pos = cur.str.find(replacePair.first, pos + 1);
}
}
}
cout << "NO ANSWER!" << endl;
}
int main()
{
cin >> from >> to;
string a, b;
while (cin >> a >> b)
{
replaceTable.push_back(pair<string, string>(a, b));
}
bfs();
return 0;
}