Description
已知有两个字串(A,B)及一组字串变换的规则(至多(6)个规则):
$ A_1 -> B_1 $
$ A_2 -> B_2 $
规则的含义为:在(A)中的子串(A_1)可以变换为(B_1),(A_2)可以变换为(B_2)…。
例如:A=abcd
,B=xyz
,
变换规则为:
abc
→xu
,ud
→y
,y
→yz
则此时,(A)可以经过一系列的变换变为(B),其变换的过程为:
abcd
→xud
→xy
→xyz
。
共进行了(3)次变换,使得(A)变换为(B)。
Input
输入格式如下:
(A) (B)
(A_1) (B_1)
(A_2) (B_2) //变换规则
... ...
所有字符串长度的上限为(20)。
Output
若在(10)步(包含(10)步)以内能将(A)变换为(B),则输出最少的变换步数;否则输出"NO ANSWER!"
Sample Input
abcd xyz
abc xu
ud y
y yz
Sample Output
3
题解
由于这题求最小步数,所以我们可以用(BFS),用(Hash)压缩状态,再就纯考验代码能力了。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxm=400010,N=231;
char s1[N],s2[N],mp[10][3][N],Q[maxm][N];
int l,r,nmp,Ans[maxm],Hash[maxm];
void Read()
{
scanf("%s %s",s1,s2);
nmp=1;
while(~scanf("%s %s",mp[nmp][1],mp[nmp][2]))
++nmp;
--nmp;
}
void Delete(char s[],int st,int len)//删除mp[][1]
{
int ls=strlen(s)-len;
for(int i=st;i<ls;++i) s[i]=s[i+len];
s[ls]=' ';
}
void Insert(char s[],int st,char mpi[])//插入mp[][2]
{
char tmp1[maxm],tmp2[maxm];
for(int i=0;i<st;++i) tmp1[i]=s[i];
tmp1[st]=' ';
int len=strlen(s);
for(int i=st;i<=len;++i) tmp2[i-st]=s[i];
strcpy(s,tmp1),strcat(s,mpi),strcat(s,tmp2);
}
int Calc(char s[])
{
int Res=0,len=strlen(s);
for(int i=0;i<len;++i)
{
Res=Res*131+s[i],
Res&=0x07FFFFFF;
}
return Res%maxm;
}
void Bfs()
{
l=r=1;
strcpy(Q[1],s1);
Ans[1]=0;
int p,QAQ; char ss[N],s[N];
while(l<=r&&Ans[l]<=10)
{
if(!strcmp(Q[l],s2))
{
printf("%d
",Ans[l]); return;
}
for(int i=1;i<=nmp;++i)
{
strcpy(ss,Q[l]);
p=strstr(ss,mp[i][1])-ss;
while(strstr(ss,mp[i][1])!=NULL)
{
strcpy(s,Q[l]),
Delete(s,p,strlen(mp[i][1])),
Insert(s,p,mp[i][2]);
QAQ=Calc(s);
if(Hash[QAQ])
{
ss[p]=' ',
p=strstr(ss,mp[i][1])-ss;
continue;
}
Hash[QAQ]=1;
strcpy(Q[++r],s); Ans[r]=Ans[l]+1;
ss[p]=' ',
p=strstr(ss,mp[i][1])-ss;
}
}
++l;
}
puts("NO ANSWER!");
}
int main()
{
Read(),Bfs();
return 0;
}