https://www.luogu.org/problem/P1032
题目描述
已知有两个字串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。
共进行了3次变换,使得A变换为B。
输入格式
输入格式如下:
A B
A1 B1
A2 B2 |-> 变换规则
… … /
所有字符串长度的上限为20。
输出格式
输出至屏幕。格式如下:
若在10步(包含10步)以内能将A变换为B,则输出最少的变换步数;否则输出"NO ANSWER!"
输入输出样例
输入 #1
abcd xyz
abc xu
ud y
y yz
输出 #1
3
代码
#include<algorithm>
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<queue>
using namespace std;
const int hashsize=1e6+10;
bool mlist[hashsize];
string src,dest,tmp;
string from[7];
string to[7];
long long sum,cnts;
long long cnt;
struct node{
string s;
int time;
node(string ss,int t){
s=ss;
time=t;
}
};
bool hash(string h){
sum=0;
for(int i=0; i<h.size(); i++){
sum*=37;
sum+=h[i];
}
sum=abs(sum%hashsize);
if(mlist[sum])return false;
mlist[sum]=true;
return true;
}
void bfs(){
queue <node> q;
q.push(node(src,0));
sum=0;
while(!q.empty()){
node t=q.front();q.pop();
if(t.s==dest){
printf("%d",t.time);
return;
}
if(t.time==10)
continue;
for(int i=0; i<cnts; i++) {
int j=-1;
while(1){
j=t.s.find(from[i],j+1);
if(j==string::npos)break;
tmp=t.s;
tmp.replace(j,from[i].size(),to[i]);
if(hash(tmp))q.push(node(tmp,t.time+1));
}
}
}
puts("NO ANSWER!");
}
int main(){
memset(mlist,false, sizeof mlist);
cin>>src;
cin>>dest;
while(cin>>from[cnts]>>to[cnts])
cnts++;
bfs();
return 0;
}