题目描述
已知有两个字串 A, B及一组字串变换的规则(至多6个规则):
A1 -> B1
A2 -> B2
规则的含义为:在A中的子串 A1可以变换为 B1、A2可以变换为 B2 …。
例如:A='abcd' B='xyz'
变换规则为:
‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’
则此时,A 可以经过一系列的变换变为 B,其变换的过程为:
‘abcd’->‘xud’->‘xy’->‘xyz’
共进行了三次变换,使得A变换为B。
输入描述:
输入格式如下:
A B
A1 B1 \
A2 B2 |-> 变换规则
... ... /
所有字符串长度的上限为 20。
输出描述:
输出格式如下: 若在10步(包含 10步)以内能将A变换为B,则输出最少的变换步数;否则输出"NO ANSWER!"
示例1
输入
abcd xyz abc xu ud y y yz
输出
3
想法:
因为早上copy了八数码的代码,晚上就想看看自己到底掌握了多少,就试试这道题了。开始感觉有点麻烦,又要删除添加字符串什么的,然后就突然意识到string类和stl的便利所在。写完后样例过了,但错了。是string相关的函数用错的原因。改了还是错了,想不到就去看网课了。发现是变换步数弄错了。最少变换步数就是最短路嘛。我是直接设了一个ans=0,满足条件就ans++。完全错了哈。都没有对应第几步变换。学她的用一个数组存
代码:
#include<bits/stdc++.h>
using namespace std;
string s,t;
string a[30],b[30];
int ans=0;
int n=0;
queue<int> q;
map<string,int> mp;
int cnt=0;
string c[30];
int bfs(string s,string t){
mp[s]=1;
cnt=1;
c[1]=s;
q.push(1);
while(!q.empty()){
if(ans>10) return 0;
int tmp=q.front();
q.pop();
for(int i=0;i<n;i++){
string cur=c[tmp];
//cout<<cur<<endl;
for(int j=0;j+a[i].size()-1<cur.size();j++){//其实不用遍历,用cur.find(a[i])判断也行,但不止一个a[i]怎么办呢
string nxt=cur;
//cout<<cur.substr(j,j+a[i].size())<<endl;
if(cur.substr(j,a[i].size())==a[i]){
nxt.insert(j,b[i]);//添加
//cout<<nxt<<endl;
nxt.erase(j+b[i].size(),a[i].size());//删除
//cout<<nxt<<endl;
if(mp.find(nxt)==mp.end()){
ans++;
mp[nxt]=cnt++;
c[cnt]=nxt;
q.push(cnt);
//cout<<ans<<endl;
if(ans>10) return 0;
if(nxt==t) return ans;
//break;
}
}
}
}
}
return 0;
}
int main(){
cin>>s>>t;
int i=0;
while(cin>>a[i]>>b[i]) { i++,n++; }//多组输入,不确定
//cout<<s<<endl<<t<<endl;
//for(int i=0;i<n;i++) cout<<"a[i]="<<a[i]<<endl<<"b[i]="<<b[i]<<endl;
if(bfs(s,t)) cout<<ans;
else cout<<"NO ANSWER";
}
于是代码变成了这样。但是段错误了,我就把所有数组开了很大,她解释了下原因,但我脑子不够用了,明天再说。这个做法也没办法全对,而且我还有一组测试用例是wa的。
代码:
#include<bits/stdc++.h>
using namespace std;
string s,t;
string a[300000],b[300000];
//int ans=0;
int n=0;
queue<int> q;
map<string,int> mp;
int cnt=0;
string c[300000];
int ans[10000000];
int bfs(string s,string t){
mp[s]=1;
ans[1]=0;
cnt=1;
c[1]=s;
q.push(1);
while(!q.empty()){
int tmp=q.front();
q.pop();
if(t==c[tmp]) return 1;
if(ans[tmp]>10) return 0;
for(int i=0;i<n;i++){
string cur=c[tmp];
//cout<<cur<<endl;
for(int j=0;j+a[i].size()-1<cur.size();j++){
string nxt=cur;
//cout<<cur.substr(j,j+a[i].size())<<endl;
if(cur.substr(j,a[i].size())==a[i]){
nxt.insert(j,b[i]);//添加
//cout<<nxt<<endl;
nxt.erase(j+b[i].size(),a[i].size());//删除
//cout<<nxt<<endl;
if(mp.find(nxt)==mp.end()){
cnt++;
ans[cnt]=ans[tmp]+1;
mp[nxt]=cnt;
c[cnt]=nxt;
q.push(cnt);
//cout<<ans<<endl;
if(ans[cnt]>10) return 0;
if(nxt==t) return 1;
//break;
}
}
}
}
}
return 0;
}
int main(){
cin>>s>>t;
int i=0;
while(cin>>a[i]>>b[i]) { i++,n++; }
//cout<<s<<endl<<t<<endl;
//for(int i=0;i<n;i++) cout<<"a[i]="<<a[i]<<endl<<"b[i]="<<b[i]<<endl;
if(bfs(s,t)) cout<<ans[mp[t]];
else cout<<"NO ANSWER";
}
知识点:
1.cin和scanf的返回值:
cin: 若输入成功则返回1,失败返回0;
scanf: 若输入成功返回输入的个数,失败返回EOF(-1).