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。
样例输入1[复制]
样例输出1[复制]
每个测试点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;
}
递交评测
查看与发表题解
查看本题递交记录
我的所有递交记录
发表题目讨论
![](https://upfiles.b0.upaiyun.com/logo/90x45.png)
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-24 | Accepted |
题目讨论
发表题目讨论08-23 | 这个题目比较屌…… |
05-11 | 样例输出什么情况 |
03-24 | C++的在Linux不能过? |
10-31 | P1124疑难 |
10-12 | 诡异的编译失败…请大牛帮忙 |
10-12 | 一个题目理解方面的问题 |
07-21 | 215 |
03-19 | 使用C语言,此题能AC吗? |
02-07 | 大牛来一下 |
![](https://upfiles.b0.upaiyun.com/logo/90x45.png)
相关文章推荐
- n皇后问题
- MySql主从复制配置示例
- servlet使用
- Attribute is missing the Android namespace prefix——android开发之xml布局文件
- Android应用程序用户界面(三)
- 使用 dd 命令进行硬盘 I/O 性能检测
- vim 配置替换错误E488: Trailing characters
- mybatis 数据库语句 标签
- C语言中的内部名和外部名
- 8皇后位操作解法
- SQL 的执行顺序分析
- JavaScript 运行机制与单线程
- mysql中varchar(N)中的N代表什么
- UITableView
- Codeforces Round #201 (Div. 2) 347A Difference Row(脑洞)
- UIControl
- JME3资源管理之四:心得和小节
- Scala学习第十一天 Scala中的apply实战详解
- Android Studio 获取证书指纹SHA1
- (五) HTTP/2的流量控制