ZOJ - 4110 Strings in the Pocket 马拉车

题目链接:https://cn.vjudge.net/problem/ZOJ-4110

题意:对称的交换a串中的一个区间,使其和b一样,问多少种方案

题解:如果存在不一样的部分,那肯定就是最左边的不一样的位置 l 和最右边的不一样的位置 r ,交换这个区间,如果可以的话,判断一下还能不能扩大,如果不行,那就是0了,如果这两个串一样,那就看,a中有多少回文串,马拉车跑一遍即可

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+100;
int T;
char a[N],b[N];
char s[N*2];
int p[N*2];
int len,lena;
bool judge(){
	int lena=strlen(a),lenb=strlen(b);
	if(lena!=lenb){
		printf("0\n");
		return 0;
	}
	int i,j;
	for(i=0;i<lena;++i)
		if(a[i]!=b[i])break;
	if(i==lena)return 1;
	for(j=lena-1;j>=0;--j)
		if(a[j]!=b[j])break;
	int ti=i,tj=j;
	while(i<=tj&&j>=ti&&a[i]==b[j]){
		i++;
		j--;
	}
	if(i<=tj && j>=ti)
		printf("0\n");
	else{
		i=ti;
		j=tj;
		int ans=0;
		
		for(int k=1;ti-k>=0&&tj+k<lena;++k){
			if(a[ti-k]==a[tj+k])ans=k;
			else break;
		}
		printf("%d\n",ans+1);
	}
	return 0;
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%s",a);
		scanf("%s",b);
		if(judge()){
			s[0]='0',s[1]='#';
			len=strlen(a);
			for(int i=0;i<len;i++)
			{
				s[i*2+2]=a[i];
				s[i*2+3]='#';
			}
			s[len*2+2]='1';
			long long  ans=0;
			int maxx=0,id;
			for(int i=2;i<=len*2+1;i++)
			{
				p[i]=maxx>i?min(p[id-(i-id)],maxx-i):1;
				while(s[i+p[i]]==s[i-p[i]]) p[i]++;
				if(i+p[i]>maxx)
				{
					maxx=i+p[i];
					id=i;
				}
				if(s[i]=='#')ans+=(p[i]-1)/2;
				else ans+=p[i]/2;
			}
			printf("%lld\n",ans);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/89643360
今日推荐