Round #313 (Div. 2) D. Equivalent Strings-大水题递归

本文探讨了如何高效地判断两个字符串是否等价,并介绍了优化算法以提高判断效率。通过将字符串拆分为子串并比较,实现了快速的等价性判断。同时,通过排序子串来进一步优化算法,避免了不必要的递归调用,有效减少了时间复杂度。

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

题目大意:给出两串长度相等的字符串a,b,问其是否为等价字符串。

                  判断依据为:1.两个字符串相等。

                                        或 2.把每个字符串拆分成长度相等的两个子串:a=a1+a2,b=b1+b2,如果a1=b2且a2=b1或者a1=b1&&a2=b2 ,则a与b等价

深搜递归判断子串是否等价,子串等价,主串就一定等价。注意子串长度相等的条件,不满足不能拆。

如此大的水题。。居然没看到。。。以后做题一定得快点。。。才有机会做后面的题。。

  有个要注意的细节是,如果用这种暴力的方法做这题

递归的时候 递归顺序  如果是 



	if 		(cmp(len/2,a1,b2)&&cmp(len/2,a2,b1))
		return 1; 
	if  	((cmp(len/2,a1,b1)&&cmp(len/2,a2,b2)))
 		return 1;
就ac 

如果2个if的顺序反了。。就是TLE ON TEST 89.......应该是这个数据太大。。递归两遍就超时了,这是之后才发现的,估计当时用暴力没过的人真是被坑了。。。


当然这种方法毕竟太暴力了,应该用更优的算法:

因为根据题目“等价”的性质,可以知道 1个个字符串,把他的两个子串互换位置是影响“等价性”的,

因此我们可以规定,一个字符串不断做这样的更换(把字典序小的子串放在前,大的在后)  直到子串长度为奇数

最后直接比较经过这样操作的a与b即可知道等不等价;




暴力法代码:


 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define INF 0x7f7f7f7f
const __int64 maxn = 200005; 


string a;
string b;
 
 string tmp;
int cmp(int len,string s1,string s2)
{
 if (s1==s2) return 1;
	if (len%2) 
			return 0;

	string	a1=s1.substr(0,len/2);
	string	a2=s1.substr(len/2,len/2);  
	string	b1=s2.substr(0,len/2);
	string	b2=s2.substr(len/2,len/2);

	if 		(cmp(len/2,a1,b2)&&cmp(len/2,a2,b1))
		return 1; 
	if  	((cmp(len/2,a1,b1)&&cmp(len/2,a2,b2)))
 		return 1;

	
	
	return 0;

}
 

int main()
{  
	//	freopen( "pulp.in","r",stdin );  //scanf 从1.txt输入
	//  freopen( "pulp.out","w",stdout );  //printf输出到1.tx
	
cin>>a;
cin>>b;

 

 	int flag=cmp(a.size(),a,b);
 	if (flag) 
		printf("YES\n");
 	else
		printf("NO\n");
	
	return 0;
}

优化法代码:

 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define INF 0x7f7f7f7f
const __int64 maxn = 200005; 


string a;
string b; 
string order(string s1)
{
	
	int len=s1.size();
	if (len%2) return s1;	//长度为奇数不能再分,包括1
	string	a1=s1.substr(0,len/2);
	string	a2=s1.substr(len/2,len/2);  
	
	string r1=order(a1);
	string r2=order(a2);
	if (r1<r2)
		return r1+r2;
	else 
		return r2+r1;

 

}
 

int main()
{  
	//	freopen( "pulp.in","r",stdin );  //scanf 从1.txt输入
	//  freopen( "pulp.out","w",stdout );  //printf输出到1.tx
	
cin>>a;
cin>>b;

 

  
 	if (order(a)==order(b)) 
		printf("YES\n");
 	else
		printf("NO\n");
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值