NOIP 2002 提高组 复赛 字串变换

本文详细解析了NOIP2002提高组复赛中的一道字串变换题目,介绍了使用广度优先遍历方法解决该问题的过程,并分享了调试经验及最终AC代码。

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

NOIP 2002 提高组 复赛 字串变换

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。

该题整整编了四天。终于AC了,2017-4-11

附上AC代码,编译环境Dev-C++4.9.9.2

#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;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值