题目概述
链接:洛谷P1032
字符串的子串(必须连续与子序列不同)有至多六种变化规则,若在10步(包含10步)以内能将A变换为B,则输出最少的变换步数;否则输出"NO ANSWER!"
题目分析
关键词“最少的变换步数”,那么首选的是广度优先遍历,从字符串A开始,遍历每一种变化规则,然后生成新的字符串入队列。同时要有一个map映射,确定以前出现过的字符串不能再次出现
题目难度:普及+/提高
AC代码
#include<bits/stdc++.h>
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指的是截取子串的长度!