P1032 字串变换 字符串BFS

本文深入探讨了一种字符串变换算法,通过一系列规则将源字符串转换为目标字符串。文章详细介绍了算法的实现过程,包括使用队列进行广度优先搜索,以及如何处理变换规则。此外,还讨论了算法在实际应用中可能遇到的问题和解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  

题目描述

已知有两个字串A,BA,B及一组字串变换的规则(至多66个规则):

A_1A1 ->B_1B1

A_2A2 -> B_2B2

规则的含义为:在 AA中的子串 A_1A1 可以变换为B_1B1A_2A2 可以变换为 B_2B2 …。

例如:AA='abcdabcd'BB='xyzxyz'

变换规则为:

abcabc’->‘xuxu’‘udud’->‘yy’‘yy’->‘yzyz’

则此时,AA可以经过一系列的变换变为BB,其变换的过程为:

abcdabcd’->‘xudxud’->‘xyxy’->‘xyzxyz’

共进行了33次变换,使得AA变换为BB。

输入输出格式

输入格式:

 

输入格式如下:

ABB
A_1A1 B_1B1
A_2A2 B_2B2 |-> 变换规则

... ... /

所有字符串长度的上限为2020。

 

输出格式:

 

输出至屏幕。格式如下:

若在1010步(包含1010步)以内能将AA变换为BB,则输出最少的变换步数;否则输出"NO ANSWER!"

 

输入输出样例

输入样例#1: 复制
abcd xyz
abc xu
ud y
y yz
输出样例#1: 复制
3

string.find("string",pos) 从pos开始搜索string

先是用map迭代器来遍历
#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define LL long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define N 1005
string s,ans;
map<string,string>mp;
struct node
{
    string str;
    int d;
};

void  bfs()
{
    node u,v;
    u.str=s;
    u.d=0;
    queue<node>q;
    q.push(u);
    while(!q.empty())
    {
         u=q.front();q.pop();
        if(u.str==ans){printf("%d\n",u.d);return ;}
        if(u.d>=10){printf("NO ANSWER!\n");return ;}
        map<string,string>::iterator it;
        for(it=mp.begin();it!=mp.end();it++)
        {
            v=u;
            v.d++;
            int pos=0;
            while((pos=v.str.find(it->first,pos))!=v.str.npos )
              {
                  pos+=1;
                  node w=v;
                  w.str=v.str.substr(0,pos-1)+it->second+v.str.substr(pos+(it->first.size())-1, v.str.size() );
                  q.push(w);
              }
        }
    }
}


int main()
{
    cin>>s>>ans;
    string a,b;
    while(cin>>a>>b)
        if(!mp.count(a))mp[a]=b;
    bfs();
}
View Code
五个点一个WA 一个MLE 
先不论那个MLE的 下载了WA的数据
abcdefgh 12345678
abcd efgh
efgh 1234
efgh 5678
数据

着实恶心。。

 

map只能一对一 

这题不用map就能过  还方便了不少  不用迭代器 

蒟蒻被自己蠢死了   用了一个麻烦还错的方法QAQ

bfs 最下面要写noanser  不然没到十次就结束了bfs岂不是什么都不输出(下载了数据才知道)

还有就是

while(cin>>fi[n]>>se[n])n++;

我一开始写成

while(cin>>fi[n]>>se[n++]);

是错的  虽然我还不知道为啥不行

还有。。注意这个map的用法

这个map真的剪枝了很多   之前那个map属实笨比

 

sub 好多细节  多看!

#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define LL long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define N 1005
string s,ans;
string fi[N];
string se[N];
int n;
struct node
{
    string str;
    int d;
};
map<string,int>mp;

string judge(string str,int i,int j)
{
    if(i+fi[j].size()>str.size())return "";
    int len=fi[j].size();
    if(str.substr(i,len)==fi[j])
        return str.substr(0,i)+se[j]+str.substr(i+len,str.size());
    
   return "";
}


void bfs()
{
    queue<node>q;
    node u,v;
    u.str=s;
    u.d=0;
    q.push(u);
    while(!q.empty())
    {
        u=q.front();q.pop();
        if(u.str==ans){printf("%d\n",u.d);return;}
        if(u.d>=10){printf("NO ANSWER!\n");return;}
        if(mp[u.str])continue;
        mp[u.str]=1;
        u.d+=1;
        rep(i,0,u.str.size()-1)
        rep(j,0,n-1)
        {
            string temp=judge(u.str,i,j);
            if(temp!="")
            {
                v=u;
                v.str=temp;
                q.push(v);
            }
        }
    }
   printf("NO ANSWER!\n");
}


int main()
{
    cin>>s>>ans;
    n=0;
    while(cin>>fi[n]>>se[n])n++;
    bfs();
}
View Code

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

















转载于:https://www.cnblogs.com/bxd123/p/10531612.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值