问题 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();
}