Mirrored String II Gym - 101350I (二分+hash)

由于不会马拉车求最长回文子串,于是就只能用二分了。然后由于长度为奇数的回文子串不存在,不代表更长的长度为偶数的回文子串不存在。但是长度为奇(偶)数的回文子串不存在,更长的长度为奇(偶)数的回文子串一定不存在,长度为奇(偶)数的回文子串存在,更短的长度为奇(偶)数的回文子串一定存在,所以可以想到对奇偶长度分开二分。比如说huuf,长度为3的回文子串是不存在的,但是长度为4的回文子串是存在的,这就不具有二分的单调性了。check函数里这个c数组是标记数组,标记i位置能否作为起点。

 

#include<bits/stdc++.h>
using namespace std;
#define fuck(x) cout<<#x<<"   "<<x<<endl;
#define ull unsigned long long
const int maxn=1e3+10;
const ull base1=13331;
const ull base2=131;
char s[maxn];
int len,c[maxn];
ull zhash1[maxn],fhash1[maxn],ipow1[maxn],zhash2[maxn],fhash2[maxn],ipow2[maxn];
vector<int>js,os;
bool check(int mid)
{
    memset(c,0,sizeof(c));
    for(int i=1;i<=len;i++)
        if(s[i]=='A'||s[i]=='H'||s[i]=='I'||s[i]=='M'||s[i]=='O'||s[i]=='T'||s[i]=='U'||s[i]=='V'||s[i]=='W'||s[i]=='X'||s[i]=='Y')
            ;
        else
        {
            c[max(1,i-mid+1)]++;
            c[i+1]--;
        }

    for(int i=1;i<=len;i++) c[i]+=c[i-1];
    for(int i=1;i<=len-mid+1;i++)
    {
        if(c[i]>=1) continue;
        int l=i,r=i+mid-1;
        if(zhash1[r]-zhash1[l-1]*ipow1[mid]==fhash1[l]-fhash1[r+1]*ipow1[mid]&&zhash2[r]-zhash2[l-1]*ipow2[mid]==fhash2[l]-fhash2[r+1]*ipow2[mid])
            return true;
    }
    return false;
}
int main()
{
    int t,ans,low,high,mid;
    scanf("%d",&t);
    ipow1[0]=1,ipow2[0]=1;
    for(int i=1;i<=1000;i++) ipow1[i]=ipow1[i-1]*base1,ipow2[i]=ipow2[i-1]*base2;
    while(t--)
    {
        js.clear();os.clear();
        scanf("%s",s+1);
        len=strlen(s+1);
        for(int i=1;i<=len;i++)
            if(i&1)
                js.push_back(i);
            else
                os.push_back(i);
        for(int i=1;i<=len;i++)
            zhash1[i]=zhash1[i-1]*base1+s[i],zhash2[i]=zhash2[i-1]*base2+s[i];
        for(int i=len;i>=1;i--)
            fhash1[i]=fhash1[i+1]*base1+s[i],fhash2[i]=fhash2[i+1]*base2+s[i];
        low=0,high=js.size()-1,ans=0;
        while(low<=high)
        {
            mid=(low+high)>>1;
            if(check(js[mid]))
                ans=js[mid],low=mid+1;
            else
                high=mid-1;
        }
        low=0,high=os.size()-1;
        while(low<=high)
        {
            mid=(low+high)>>1;
            if(check(os[mid]))
                ans=max(ans,os[mid]),low=mid+1;
            else
                high=mid-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2019-05-21 22:53  eason99  阅读(95)  评论(0编辑  收藏  举报