Strings in the Pocket ZOJ - 4110

Strings in the Pocket

直达车


题目大意:

建议不会马拉车的朋友先去看看马拉车算法在来看看这题,如果会的话请往下看。

首先会给你一个数字n表示有n组测试用例,每组测试用例有两个字符串。要求是把一个字符串中的一部分反转使其与第二个字符串相等。


代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <cstring>
#include <queue>
typedef long long ll;
using namespace std;
string q,w,t;
int p[4000020];
ll  manacher() {
	t="$";
	for(int a=0; a<q.length(); a++) {
		t+="#";
		t+=q[a];
	}
	t+="#@";
	for(int a=0; a<t.length(); a++)p[a]=0;
	ll re=0;
	int mx=0,id=0;
	for(int a=1; a< t.length()-1; a++) {
		if(a<mx)p[a]=min(mx-a,p[2*id-a]);
		else p[a]=1;
		while(t[a-p[a]]==t[a+p[a]])p[a]++;
		if(a+p[a]>mx)mx=a+p[a],id=a;
		re+=p[a]/2;
	}
	return re;
}
int n;
int main() {
	ios::sync_with_stdio(false);//此行和下一行用来加快输入输出
	cin.tie(0);
	while(cin>>n) {
		while(n--) {
			cin>>q>>w;
			int len=q.length();
			ll ans=0;
			if(q!=w) { //判断两个字符串是否相等
				int st=len+1;
				int en=-1;
				for(int a=0; a<len; a++) { //找出不同串的起点
					if(q[a]!=w[a]) {
						st=a;
						break;
					}
				}
				for(int a=len-1; a>=0; a--) { //找出不同串的终点
					if(q[a]!=w[a]) {
						en=a;
						break;
					}
				}

				bool ok=1;
				for(int a=st; a<=en; a++) {    //判断不同的串是否可以通过反转来变得相同 
					if(q[a]!=w[en-(a-st)]) {
						ok=0;
						break;
					}
				}
				if(ok) {//如果可以的话给ans赋值,并往两边找回文的长度 
					ans=1;
					int j=1;
					while(st-j>=0&&en+j<len&&q[st-j]==q[en+j]) {//往两边你找回文的长度 
						ans++;
						j++;
					}
				}
			} else {
				ans=manacher();
			}
			cout<<ans<<endl;

		}
	}
	return 0;
}

代码思路:

我把这题分为两个情况:

1:当两个字符串相等的时候,如果两个字符串相等的话,就是在这个字符串中找出所有的回文串的数量就是简单的马拉车

2:当这连个字符串不一样的时候,首先要判断这连个字符串中不相等的部分是否可以通过反转来使者两个字符串相关等,如果不行答案就是0;否则从不行等的位置开始往两端扩散着找看看他两端有多少是对称的,这一部分在反转后仍然相等,所以答案就是对称部分的长度加上1(自身)。

感觉其实这题只要可以想到找回文,并且会马拉车算法的话其实不难。


趁年轻,别给自己后悔的机会,错过了就什么都来不及了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值