这题有人能帮忙看看这种做法的复杂度吗……
查看原帖
这题有人能帮忙看看这种做法的复杂度吗……
97448
yspm楼主2020/10/4 12:08

我直接在一个串上面二分找最远的回文部分

然后枚举所有的回文部分在另一个串上面匹配

(目测复杂度 O(n2)O(n^2) 结果给过去了……)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define reg register
namespace yspm{
    inline int read()
    {
        int res=0,f=1; char k;
        while(!isdigit(k=getchar())) if(k=='-') f=-1;
        while(isdigit(k)) res=res*10+k-'0',k=getchar();
        return res*f;
    }
    #define ull unsigned long long
    const int N=1e5+10;
    const ull base=13331;
    ull p[N];
    struct node{
        ull h1[N],h2[N];
        char s[N];
        int len,lpos[N],rpos[N];
        inline ull get1(int l,int r){return h1[r]-h1[l-1]*p[r-l+1];}
        inline ull get2(int l,int r){return h2[l]-h2[r+1]*p[r-l+1];}
        inline void prework(char *t) 
        {
            for(reg int i=1;i<=len;++i) h1[i]=h1[i-1]*base+s[i];
            for(reg int i=len;i>=1;--i) h2[i]=h2[i+1]*base+s[i];
            return ;
        }
        inline pair<int,int> calc1(int id)
        {
            int l=1,r=len,ans=1;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(id-mid+1<1||id+mid-1>len){r=mid-1; continue;}
                if(get1(id,id+mid-1)==get2(id-mid+1,id)) l=mid+1,ans=mid;
                else r=mid-1;
            }return make_pair(id-ans+1,id+ans-1);
        }
        inline pair<int,int> calc2(int L,int R)
        {
            int l=1,r=len,ans=1;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(L-mid+1<1||R+mid-1>len){r=mid-1;}
                if(get2(L-mid+1,L)==get1(R,R+mid-1)) l=mid+1,ans=mid;
                else r=mid-1;
            }
            return make_pair(L-ans+1,R+ans-1);
        }
    }s1,s2;
    int mx=0;
    char s[N];
    inline bool check(int st1,int st2)//s1 to the left,s2 to th right
    {
        int ans=0,l=1,r=s1.len;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(st1-mid+1<1||st2+mid-1>s1.len){r=mid-1; continue;}
            if(s1.get2(st1-mid+1,st1)==s2.get1(st2,st2+mid-1)) l=mid+1,ans=mid;
            else r=mid-1;
        } 
        if(ans) mx=max(mx,ans*2+st2-st1);
        return ans;
    }
    signed main()
    {
        p[0]=1; for(reg int i=1;i<N;++i) p[i]=p[i-1]*base; 
        s1.len=s2.len=read();
        scanf("%s",s1.s+1); s1.prework(s);
        scanf("%s",s2.s+1); s2.prework(s);
        for(reg int i=1;i<=s1.len;++i) 
        {
            pair<int,int> tmp=s1.calc1(i);
            int lpos=tmp.first,rpos=tmp.second;
            for(reg int j=lpos;j<=i;++j) if(check(j-1,2*i-j)) break;
        }
        for(reg int i=1;i<=s1.len;++i) 
        {
            pair<int,int> tmp=s2.calc1(i);
            int lpos=tmp.first,rpos=tmp.second;
            for(reg int j=lpos;j<=i;++j) if(check(j,2*i-j+1)) break;
        }
        for(reg int i=1;i<s1.len;++i) 
        {
            //偶回文,中心是 (i,i+1)
            if(s1.s[i]!=s1.s[i+1]) continue; 
            pair<int,int> tmp=s1.calc2(i,i+1);
            int lpos=tmp.first,rpos=tmp.second;
            for(reg int j=lpos;j<=i;++j) if(check(j-1,2*i+1-j)) break;
        }
        for(reg int i=1;i<s1.len;++i)
        {
            if(s2.s[i]!=s2.s[i+1]) continue;
            pair<int,int> tmp=s2.calc2(i,i+1);
            int lpos=tmp.first,rpos=tmp.second;
            for(reg int j=lpos;j<=i;++j) if(check(j,2*i+2-j)) break;
        }
        //上下中心
        for(reg int i=1;i<=s1.len;++i)
        {
            if(s1.s[i]!=s2.s[i]) continue;
            int ans=1,l=1,r=s1.len;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(s1.get2(i-mid+1,i)==s2.get1(i+1,i+mid-1)) ans=mid,l=mid+1;
                else r=mid-1; 
            }mx=max(mx,ans<<1);
        } cout<<mx<<endl;
        return 0;
    }
}
signed main(){return yspm::main();}
2020/10/4 12:08
加载中...