您的位置:首页 > 其它

noip2002 字串变换 (双向宽搜,交替扩展)

2015-08-28 19:08 363 查看
P1124字串变换
Accepted

标签:搜索
搜索与剪枝NOIP提高组2002


描述

已知有两个字串 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!"


样例1

样例输入1[复制]

abcd xyz
abc xu
ud y
y yz


样例输出1[复制]

3



限制

每个测试点1s


来源

noip2002提高组第二题

解析:设从正向开始扩展的状态储存在q数组,[l1,l2]为当前正向扩展出的状态,p数组以及l2,r2的定义类似。
           正向每扩展出一个状态,就在[l2,r2]中暴力查找是否存在相同的状态,若有,则得到答案。
           逆向扩展与正向扩展类似。
          我这里采用的是交替扩展,即正向扩展一次,然后逆向扩展一次。当然,也可以每次选择状态数更少的那个进行扩展,实际上这种方法更好。
代码:
#include<cstdio>
#include<cstring>
#define maxn 100000
#define max_len 50
using namespace std;

char q[maxn+10][max_len+10];
char p[maxn+10][max_len+10];
char x[10][max_len],y[10][max_len];
int n=0,add[10],xl[10],yl[10];

int main()
{
int i,j,k,xx,step,len;
char jiewei;

scanf("%s%s",q[0],p[0]);
jiewei=p[0][strlen(p[0])];
while(scanf("%s%s",x
,y
)==2)
{
xl
=strlen(x
),yl
=strlen(y
);
add
=yl
-xl
;
n++;
}

if(n==0)
{
if(strcmp(q[0],p[0])==0)printf("0\n");
else printf("NO ANSWER!\n");
return 0;
}

int l1=0,r1=0,s1=0;
int l2=0,r2=0,s2=0;
for(step=1;step<=5;step++)
{
for(i=0;i<n;i++)
for(j=l1;j<=r1;j++)
for(len=strlen(q[j]),k=0;k<len && len+add[i]<max_len;k++)
if(strncmp(x[i],q[j]+k,xl[i])==0)
{
s1++;
strncpy(q[s1],q[j],k);
strncpy(q[s1]+k,y[i],yl[i]);
strncpy(q[s1]+k+yl[i],q[j]+k+xl[i],len-k-xl[i]);
q[s1][len+add[i]]=jiewei;

for(xx=l2;xx<=r2;xx++)
if(strcmp(p[xx],q[s1])==0)
{
printf("%d\n",step+step-1);
return 0;
}
}
if(s1!=r1)l1=r1+1,r1=s1;

for(i=0;i<n;i++)
for(j=l2;j<=r2;j++)
for(len=strlen(p[j]),k=0;k<len && len-add[i]<max_len;k++)
if(strncmp(y[i],p[j]+k,yl[i])==0)
{
s2++;
strncpy(p[s2],p[j],k);
strncpy(p[s2]+k,x[i],xl[i]);
strncpy(p[s2]+k+xl[i],p[j]+k+yl[i],len-k-yl[i]);
p[s2][len-add[i]]=jiewei;

for(xx=l1;xx<=r1;xx++)
if(strcmp(q[xx],p[s2])==0)
{
printf("%d\n",step+step);
return 0;
}
}
if(s2!=r2)l2=r2+1,r2=s2;
}
printf("NO ANSWER!\n");
return 0;
}

递交评测
查看与发表题解
查看本题递交记录


我的记录

我的所有递交记录

07-24Accepted


题目讨论

发表题目讨论
08-23这个题目比较屌……
05-11样例输出什么情况
03-24C++的在Linux不能过?
10-31P1124疑难
10-12诡异的编译失败…请大牛帮忙
10-12一个题目理解方面的问题
07-21215
03-19使用C语言,此题能AC吗?
02-07大牛来一下


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: