字串变换[NOIP2002]

本文介绍了一种使用双向广度优先搜索算法解决特定字符串替换问题的方法。通过匹配和替换字符串中的特定部分,该算法能够有效地寻找最优解。文章详细展示了如何实现这一算法,并提供了一个完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

传送门

思路

这道题其实就是双向广搜。
不过具体实现过程略显繁琐,请细心阅读。
首先,
我们需要找到 A A A中与 A i A_i Ai匹配的部分,

bool jg(char *str,int num,int flag)
{
	char *now=(flag?a[num]:b[num]);
	int len=strlen(now);
	for(int i=0;i<len;i++)
		if(now[i]!=str[i])return 0;
	return 1;
}

之后将匹配部分换成 B i B_i Bi.

for(int i=0;i<len;i++)
		{
			for(int j=1;j<n;j++)
				if(jg(q1[l1].s+i,j,1))
				{
					r1++;
					int k=0,l=0;
					while(k<i)
					{
						q1[r1].s[k]=q1[l1].s[k];
						k++;
					}
					while(l<strlen(b[j]))q1[r1].s[k++]=b[j][l++];//将Ai部分替换为Bi
					l=i+strlen(a[j]);//续上
					while(l<len)q1[r1].s[k++]=q1[l1].s[l++];
					q1[r1].s[k]=0;
					q1[r1].ans=q1[l1].ans+1;
				}
		}

同理,
B串也是如此。
最后答案也就是两边同时进行的步骤和。

AC code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdlib>
using namespace std;
const int N=10006;
struct node
{
	char s[36];int ans;
}q1[N],q2[N];char a[7][26],b[7][36];
int n;
bool pd(char *s1,char *s2)
{
	if(strlen(s1)!=strlen(s2))return 0;
	int len=strlen(s1);
	for(int i=0;i<len;i++)
		if(s1[i]!=s2[i])return 0;
	return 1;
}
bool jg(char *str,int num,int flag)
{
	char *now=(flag?a[num]:b[num]);
	int len=strlen(now);
	for(int i=0;i<len;i++)
		if(now[i]!=str[i])return 0;
	return 1;
}
void bfs()
{
	int l1,r2,l2,r1;l1=r1=l2=r2=1;
	while(l1<=r1&&l2<=r2)
	{
		if(q1[l1].ans+q2[l2].ans>10)
		{
			puts("NO ANSWER!");
			return;
		}
		int len=strlen(q1[l1].s);
		for(int i=0;i<len;i++)
		{
			for(int j=1;j<n;j++)
				if(jg(q1[l1].s+i,j,1))
				{
					r1++;
					int k=0,l=0;
					while(k<i)
					{
						q1[r1].s[k]=q1[l1].s[k];
						k++;
					}
					while(l<strlen(b[j]))q1[r1].s[k++]=b[j][l++];
					l=i+strlen(a[j]);
					while(l<len)q1[r1].s[k++]=q1[l1].s[l++];
					q1[r1].s[k]=0;
					q1[r1].ans=q1[l1].ans+1;
					for(int w=1;w<=r2;w++)
						if(pd(q1[r1].s,q2[w].s))
						{
							printf("%d\n",q1[r1].ans+q2[w].ans);
							return ;
						}
				}
		}
		len=strlen(q2[l2].s);
		for(int i=0;i<len;i++)
		{
			for(int j=1;j<n;j++)
				if(jg(q2[l2].s+i,j,0))
				{
					r2++;
					int k=0,l=0;
					while(k<i)
					{
						q2[r2].s[k]=q2[l2].s[k];
						k++;
					}
					while(l<strlen(a[j]))q2[r2].s[k++]=a[j][l++];
					l=i+strlen(b[j]);
					while(l<len)q2[r2].s[k++]=q2[l2].s[l++];
					q2[r2].s[k]=0;
					q2[r2].ans=q2[l2].ans+1;
					for(int w=1;w<=r1;w++)
						if(pd(q2[r2].s,q1[w].s))
						{
							printf("%d\n",q2[r2].ans+q1[w].ans);
							return ;
						}
				}
		}
		++l1;++l2;
	}
	puts("NO ANSWER!");
}
int main()
{
	scanf("%s%s",q1[1].s,q2[1].s);
	n=1;
	while(cin>>a[n]>>b[n])n++;
	q1[1].ans=q2[1].ans=0;
	bfs();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值