2019浙江省赛 Strings in the Pocket【manacher】

Strings in the Pocket

题目链接

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

题意

给你两个字符串,问有多少种方法能使翻转a中一个的子串后能够和b相同

题解

分两种情况

  1. a和b相同:用马拉车求回文子串个数
  2. a和b不同:记录第一个和最后一个a不同于b的位置L和R,判断[L,R]是不是回文串,如果不是,答案为0;如果是,匹配a的前部和b的后部、a的后部和前部,看能匹配几次

代码

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define scac(x) scanf("%c",&x)
#define sca(x) scanf("%d",&x)
#define sca2(x,y) scanf("%d%d",&x,&y)
#define sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define scl(x) scanf("%lld",&x)
#define scl2(x,y) scanf("%lld%lld",&x,&y)
#define scl3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define pri(x) printf("%d\n",x)
#define pri2(x,y) printf("%d %d\n",x,y)
#define pri3(x,y,z) printf("%d %d %d\n",x,y,z)
#define prl(x) printf("%lld\n",x)
#define prl2(x,y) printf("%lld %lld\n",x,y)
#define prl3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define ll long long
#define LL long long
inline ll read(){ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;}
#define read read()
#define pb push_back
#define mp make_pair
#define P pair<int,int>
#define PLL pair<ll,ll>
#define PI acos(1.0)
#define eps 1e-6
#define inf 1e17
#define INF 0x3f3f3f3f
#define MOD 998244353
#define mod 1e9+7
#define N 2000005
const int maxn=2e5+5;
int t;
int len,cnt;
char a[N],b[N],c[N],tmp[N<<1];
int Len[N<<1];

int init(char *st)
{
    int i,len=strlen(st);
    tmp[0]='@';
    for(i=1;i<=2*len;i+=2)
    {
        tmp[i]='#';
        tmp[i+1]=st[i/2];
    }
    tmp[2*len+1]='#';
    tmp[2*len+2]='$';
    tmp[2*len+3]=0;
    return 2*len+1;
}
void manacher(char *st,int len)
{
    ll ans=0;
    int mx=0,po=0;
    int l=0,r=0;//
    for(int i=1;i<=len;i++)
    {
        if(mx>i)
            Len[i]=min(mx-i,Len[2*po-i]);
        else
            Len[i]=1;
        while(st[i-Len[i]]==st[i+Len[i]])
            Len[i]++;
        if(Len[i]+i>mx)
        {
            mx=Len[i]+i;
            po=i;
        }
        l=(i-1)/2-(Len[i]-1)/2;
        r=(i-1)/2+(Len[i]-1)/2;
        if(Len[i]&1) r--;
        ans+=((r-l+2)/2);
    }
    printf("%lld\n",ans);
    return ;
}
int main(){
  t = read;
  while(t--){
    scanf("%s",a);
    scanf("%s",b);
    if(strcmp(a, b) == 0) {
	     int len = init(a);
	     manacher(tmp, len);
    	 continue;
    }
    len = strlen(a);
    int l = 0, r = len-1;
    while(l < len){
      if(a[l] != b[l])break;
      l++;
    }
    while(r >= 0){
      if(a[r]!=b[r])break;
      r--;
    }
    strcpy(c,a);
    int tot = l;
    for(int i = r; i >= l; i--)
      c[tot++] = a[i];
    int ans = 1;
    for(int i = 0; i < len; i++){
        if(b[i] != c[i]){
            ans = 0;
            break;
        }
    }
    if(ans){
      l--,r++;
      while(l >=0 && r < len){
        if(a[l] != b[r] || a[r] != b[l])
          break;
        ans++;
        l--;r++;
      }
    }
    pri(ans);
  }
  return 0;
}

posted @ 2019-04-28 21:53  llke  阅读(125)  评论(0)    收藏  举报