网课:[NOIP2002]字串变换——牛客(疑问)

文章介绍了通过广度优先搜索解决字符串A到B的最少变换问题,涉及C++编程和字符串操作技巧。作者通过实例展示了如何运用这些技术来寻找最短路径。
摘要由CSDN通过智能技术生成

题目描述

已知有两个字串 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).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值