思路:
子串变换,本题打算先用迭代加深搜索来做,然后的话加上一个map判重剪枝。(这题重点是练一下字符串函数,很少做字符串的搜索题)
string中find()返回值是字母在母串中的位置(下标记录),如果没有找到,那么会返回一个特别的标记npos,也就是-1。(map用过)
#include<iostream>
using namespace std;
int main()
{
string str1="She drinks too much!";
str1=str1.replace(str1.begin(),str1.begin()+3,"He");
cout<<str1<<endl;//原串从下标为0数的3个字符She用He替换
string s="Hello!c";
char c='h';
s=s.replace(0,6,5,c);//原串从下标为0的6个字符用5个字符h替换
cout<<s<<endl;
string str2="Good morning! Enjoy youself!";
string s2="A good evening..";
str2=str2.replace(5,8,s2,7,9);//s2从下标7开始的9个字符来替换s1从下标5开始的8个字符
cout<<str2<<endl;
return 0;
}
改题该题原本想用map存储组合,但后来发现容易有冲突,所以又改成了string字符串数组,直接string s[3]就好了。
#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
using namespace std;
string book1[7],book2[7];
map<string,int> mark;
string bgi,edi;
int top=0;
bool sus=0;
void dfs(string cur,int step,int maxn){
if(step==maxn){(满足到达的深度数就退出)
if(cur==edi)sus=1;
return ;
}
if(sus)return ;
if(mark[cur]!=0&&step>=mark[cur])return ;(记忆化剪枝,要是当前是处在同一层搜索区域内撞上了就返回(因为之前有比它小的,肯定之前的状态怎样都会比它小))
mark[cur]=step;
for(int i=1;i<=top;i++){
string now=book1[i];
int k=0;
int loc=cur.find(now,0);(这里有个坑,就是它只会找第一个,加个for循环全部试一遍!)
for(;loc!=cur.npos;loc=cur.find(now,k)){
k=loc+1;(记录下一个位置)
string temp=cur;
string tem=cur.replace(loc,now.length(),book2[i]);
cur=temp;(注意:cur也会发生改变,要备份一下)
dfs(tem,step+1,maxn);
}
}
}
int main(){
cin>>bgi>>edi;
mark[bgi]=1;
string a,b;
while(top<6&&cin>>a>>b){(输入没有结束,cin就返回为真,否则的话返回为假)
top++;
book1[top]=a;
book2[top]=b;(这里不能用map,因为会有冲突)
}
for(int maxd=0;maxd<=10;maxd++){(迭代加深搜索)
dfs(bgi,0,maxd);
mark.clear();(这里记得clear一下,不然的话后面的搜索会被前面的所制约住(因为他们找的路径是一样的,这种情况下很容易满足剪枝条件))
if(sus){
printf("%d",maxd);
return 0;
}
}
printf("NO ANSWER!");
}
总结:看着似乎很简单其实一堆坑,例如函数的使用(自己不熟)、以及途中搜索之类的,这题除了用迭代加深搜索+剪枝+记忆化搜索可以做出来之外,还可以用双向BFS,具体的放在另外一个题解。