【NOIP2002】字串变换 -宽搜

问题 F(1209): 【NOIP2002】字串变换
时间限制: 1 Sec 内存限制: 64 MB
题目描述
已知有两个字串 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!”

样例输入
abcd xyz
abc xu
ud y
y yz
样例输出
3
提示

也是普通宽搜,但判重很重要:hash少不了,再来一个邻接表
还有一个剪枝(代码中没有写):当(10-u.step)*一步最多能减少的字符长度

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXL 50
#define MAXR 6
#define MAXSTA 100000
#define MAXH 999997

struct node{
    int len,step;
    char s[MAXL+5];
    node(){}
    node(char *a,int b,int c){
        strcpy(s,a);
        len=b;
        step=c;
    }
};

struct node2{
    int lenx,leny;
    char x[MAXL+5],y[MAXL+5];
}r[MAXR+10];

int cntr,cntp,cntu,Next[MAXSTA+10],head[MAXH+10];
char a[MAXL+10],b[MAXL+10],st[MAXSTA+10][MAXL+10];

int hash(char *str,int len) //BKDR
{
    int seed=131,ret=0;
    for(int i=0;i<len;i++)
        ret=ret*seed+str[i];
    return ret%MAXSTA;
}
int search(char *str,int len)
{

    int h=hash(str,len);
    int u=head[h];
    while(u){
        if(!strcmp(str,st[u]))
            return true;
        u=Next[u];
    }
    strcpy(st[++cntu],str);
    Next[cntu]=head[h];
    head[h]=cntu;
    return false;
}
void BFS()
{
    int k;
    node u;
    queue<node> que;
    queue<int> reuse;
    if(!search(a,strlen(a)))
        que.push(node(a,strlen(a),0));
    char cur[MAXL+5];
    while(!que.empty()){
        u=que.front();  que.pop();
        for(int i=0;i<cntr;i++){
            for(int j=0;j<u.len;j++){
                if(j+r[i].lenx>u.len)
                    continue;
                for(k=0;u.s[j+k]==r[i].x[k]&&k<r[i].lenx;k++);
                if(k==r[i].lenx){
                    memset(cur,0,sizeof cur);
                    int lenc=0;
                    for(k=0;k<j;k++)
                        cur[lenc++]=u.s[k];
                    for(k=0;k<r[i].leny;k++)
                        cur[lenc++]=r[i].y[k];
                    for(k=min(r[i].lenx+j,u.len);k<u.len;k++)
                        cur[lenc++]=u.s[k];

                    if(!strcmp(cur,b)){
                        printf("%d\n",u.step+1);
                        return ;
                    }

                    if(u.step+1<10){
                        if(!search(cur,lenc))
                            que.push(node(cur,lenc,u.step+1));
                    }
                }
            }
        }
    }
    printf("NO ANSWER!\n");
}
int main()
{
    scanf("%s%s",a,b);
    while(scanf("%s%s",r[cntr].x,r[cntr].y)!=EOF){
        if(strcmp(r[cntr].x,r[cntr].y)){
            r[cntr].lenx=strlen(r[cntr].x);
            r[cntr].leny=strlen(r[cntr].y);
            cntr++;
        }
    }
    BFS();
}
posted @ 2016-01-30 10:45  KatarinaYuan  阅读(242)  评论(0编辑  收藏  举报