题目描述

已知有两个字串 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
\
|-> 变换规则
... ... /
所有字符串长度的上限为 20。

输出描述:

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

示例1

输入
abcd xyz
abc xu
ud y
y yz
输出
3

解答

1.读完题目,样例模拟成功,但感觉该题挺难的,无从下手。
2.搜索网络后,才明白,因为有多种变换规则,故一次变换有多种可能,故采用广度优先遍历方法。
3.数据输入量:至多6个规则 所有字符串长度的上限为 20
4.感觉该题比较简单,编码,提交60分,测试点4,5 均RE。
5.将队列q[1000]改成q[10000],测试点4通过,测试点5还是RE,再改大数组还是无功而返。单向搜索,80分到头。
6.采用双向搜索,参考他人代码,收获很大,但提交还是80分,无奈只好对拍,才发现字符串变换出了问题,必须整个字符串搜索完毕,按规则逐个变换才能算一步变换结束,之前的问题是,字符串只变化第一次找到的字符,没有第二次第三次查找,算法存在较大问题。
7.问题找到后,开始修改,工程量不小。
8.核心代码:p=strstr(b+d+strlen(left[i]),left[i]);//查找剩下的字符串,该题最难之处 
9.修改,提交AC。

#include <stdio.h>
#include <string.h>
char input[100],output[100];
int lena=0;
struct node{
    char in[30];//in[100]
    int s;//步数 
}q1[1000],q2[1000];//q[1000]
char left[10][30],right[10][30];//变换规则 
void bfs(char *input,char *output){
    int h1,t1,i,j,d,h2,t2;
    char b[30],*p;//b[100]
    
    h1=t1=0;
    strcpy(q1[t1].in,input);
    q1[t1].s=0;
    t1++;
    
    h2=t2=0;
    strcpy(q2[t2].in,output);
    q2[t2].s=0;
    t2++; 
    
    if(strcmp(q1[t1-1].in,q2[t2-1].in)==0){
        printf("%d\n",q1[t1-1].s+q2[t2-1].s);
        return;
    }
    while(h1<t1&&h2<t2){
        if(q1[h1].s+q2[h2].s>10)
            break;
        strcpy(b,q1[h1].in);
        for(i=0;i<lena;i++){//变换处理
            p=strstr(b,left[i]);
            while(p!=NULL){
                d=p-b;
                strncpy(q1[t1].in,b,d);
                strcat(q1[t1].in,right[i]);
                strcat(q1[t1].in,&b[d+strlen(left[i])]);
                q1[t1].s=q1[h1].s+1;
                for(j=0;j<t2;j++)
                    if(strcmp(q1[t1].in,q2[j].in)==0){
                        printf("%d\n",q1[t1].s+q2[j].s);
                        return;
                    }
                t1++;
                p=strstr(b+d+strlen(left[i]),left[i]);//查找剩下的字符串,该题最难之处 
            } 
        }
        h1++;
        
        strcpy(b,q2[h2].in);
        for(i=0;i<lena;i++){//变换处理
            p=strstr(b,right[i]);
            while(p!=NULL){//原来是if,现改成while 
                d=p-b;
                strncpy(q2[t2].in,b,d);
                strcat(q2[t2].in,left[i]);
                strcat(q2[t2].in,&b[d+strlen(right[i])]);
                q2[t2].s=q2[h2].s+1;
                for(j=0;j<t1;j++)
                    if(strcmp(q2[t2].in,q1[j].in)==0){
                        printf("%d\n",q1[j].s+q2[t2].s);
                        return;
                    }
                t2++;
                p=strstr(b+d+strlen(right[i]),right[i]);//用了比较长的时间才理解。 
            } 
        }
        h2++;
    }
    printf("NO ANSWER!\n");
}
int main(){
    int i,j;
    char a[30],b[30];
    scanf("%s%s",input,output);//读取变换前后字符串 
    while(scanf("%s%s",a,b)==2){//读取变换规则 
        strcpy(left[lena],a);
        strcpy(right[lena],b);
        lena++;
    }
    bfs(input,output);
    return 0;
}


来源:mrcrack