字符变换

洛谷 P1032 字串变换

题目描述

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

A1 -> B1
​A2 -> B2

规则的含义为:在 A中的子串 A1可以变换为 B1 ,A2可以变换为B2 …。

例如:A=‘abcd’BB=’xyz’

变换规则为:

‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’

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

‘abcd’->‘xud’->‘xy’->‘xyz’

共进行了3次变换,使得A变换为B。

输入输出格式

输入格式:
输入格式如下:

A B
A1 B1
A2 B2 |-> 变换规则

… … /

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

输出格式:
输出至屏幕。格式如下:

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


最短路用bfs…

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n=0,ans=-1;
char c[6][25],d[6][25];
char a[40],b[40];
struct T{
    int l;
    char s[40];
}q[10000005];//按我这种方法数组要够大才行 TAT 
int find(int s,char x[],char y[])//从s开始在x中找y 
{
    int lx=strlen(x),ly=strlen(y);
    if(lx-s<ly)
        return -1;
    int flag;
    for(int i=s;i<=lx-ly;++i)
    {
        if(x[i]==y[0])
        {
            flag=1;
            int j=1;
            while(j<ly)
            {
                if(x[i+j]!=y[j])
                {
                    flag=-1;
                    break;
                }
                j++;
            }
            if(flag==1)
                return i;
        }
    }
    return -1;
}
void del(char x[],char y[],int s,int l)//y变成x,然后从s开始删l个 
{
    int xx=strlen(x);
    memset(y,'\0',sizeof(y));
    memcpy(y,x,xx);
    int i=0;
    while(s+i+l<xx)
    {
        y[s+i]=y[s+i+l];
        i++;
    }
    if(y[xx-l]!='\0')
    	y[xx-l]='\0';
}
void trans(char x[],char y[],int s)//在x里从s开始插入y 
{
    int ly=strlen(y);
    int lx=strlen(x);
    for(int i=lx+ly-1;i>s;--i)
    {
    	x[i]=x[i-ly];
	}
	if(x[lx+ly]!='\0')
		x[lx+ly]='\0';
    for(int i=s;i<s+ly;++i)//不能=s+ly 
    {
        x[i]=y[i-s];
    }
}
int equal(char x[],char y[])//判等 
{
    int lx=strlen(x),ly=strlen(y);
    if(lx!=ly)
        return -1;
    for(int i=0;i<lx;++i)
        if(x[i]!=y[i])
            return -1;
    return 1;
}
void bfs()
{
    int h=0,t=1;
    int x,l;
    q[1].l=0;
    x=strlen(a);
    for(int i=0;i<x;++i)
        q[1].s[i]=a[i];
    do{
        h++;
        for(int i=0;i<n;++i)
        {
        	if(q[h].l>=10)//剪枝,不剪可能出不去... 
        		break;
        	x=-1;
            l=strlen(c[i]);
            while(1)//可能含有多个 
            {
            	x=find(x+1,q[h].s,c[i]);
            	if(x==-1)
					break;
            	t++;
            	del(q[h].s,q[t].s,x,l);
            	trans(q[t].s,d[i],x);
            	q[t].l=q[h].l+1;
            	if(equal(q[t].s,b)==1)
            	{
                	ans=q[t].l;
                	return;
            	}
			}
        }
    }while(h<t);
}
int main(){
    cin>>a>>b;
    while(cin>>c[n]>>d[n])
        n++;
    bfs();
    if(ans==-1)
        printf("NO ANSWER!\n");
    else
        printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值