zoukankan      html  css  js  c++  java
  • 2019浙江省赛K zoj4110 Strings in the Pocket(manachar)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6012

    题意

    给你两个串,可以翻转a串的一个区间,问有多少对l,r使得翻转后的a串等于b串

    题解

    • 沙比提,比赛时想了想两个串相等就用马拉车求回文子串个数,觉得两个串不相等情况很复杂就没想下去了,其实两个串不相等的情况更好处理
    • 两个串不一样的话,一定需要翻转第一个和最后一个不相等的位置(关键),判一下中间是不是回文串,然后维护一下两边即可
    • 特判只有一个字符不相等的时候

    代码

    #include<bits/stdc++.h>
    #define MAXN 2000005
    #define ll long long 
    using namespace std;
    char a[MAXN],b[MAXN];
    int n,odd[MAXN],eve[MAXN],T;
    ll manachar(){
    	int l=0,r=0,x;
    	ll ans=0;
    	for(int i=1;i<=n;i++){
    		if(i>r)x=1;
    		else x=min(odd[l+r-i],r-i);
    		while(i-x>=1&&i+x<=n&&a[i-x]==a[i+x])x++;
    		odd[i]=x;
    		ans+=x;
    		if(i+x-1>r){r=i+x-1;l=i-x+1;}
    	}
    	l=r=0;
    	for(int i=1;i<=n;i++){
    		if(i>r)x=0;
    		else x=min(eve[l+r-i+1],r-i+1);
    		while(i-x-1>=1&&i+x<=n&&a[i-x-1]==a[i+x])x++;
    		eve[i]=x;
    		ans+=x;
    		if(i+x>=r){l=i-x;r=i+x-1;}
    	}
    	return ans;
    }
    int main(){
    	cin>>T;
    	while(T--){
    		scanf("%s",a+1);scanf("%s",b+1);
    		n=strlen(a+1);
    		int L=1,R=n;
    		for(;L<=n;L++)if(a[L]!=b[L])break;
    		for(;R>=1;R--)if(a[R]!=b[R])break;
    		if(L==R){printf("0
    ");continue;}
    		else if(L<=n){
    			int ans=1;
    			for(int i=L;i<=R;i++){
    				if(a[i]!=b[L+R-i]){ans=0;break;}
    			}
    			if(ans){
    				L--;R++;
    				while(L>=1&&R<=n&&a[L]==b[R]&&a[R]==b[L]){ans++;L--;R++;}
    			}
    			printf("%d
    ",ans);
    		}else{
    			printf("%lld
    ",manachar());
    		}
    	}
    }
    
  • 相关阅读:
    day08超市商品库存案例
    day07
    day06_03
    day06_02
    day06_01
    最简单的库存管理java案例
    Day05_homework
    方法的使用注意事项
    day05
    冒泡排序
  • 原文地址:https://www.cnblogs.com/VIrtu0s0/p/10781700.html
Copyright © 2011-2022 走看看