湖南大学第十五届程序设计竞赛(最长回文公共子串)H-Longest Common Palindrome Substring(强大的思维+哈希+马拉车)

https://ac.nowcoder.com/acm/contest/908/H

题意:就是求两个串的最长公共回文子串;

做法:当时那道题撒逼了,以为是一道后缀数组题,结果写了一个小时没写出来,但不过又有人用后缀数组过了,果然自己太弱了。后来想到了马拉车和哈希,这个思路是正确的。就是对任意一个串进行马拉车。找出来他的每个位置的最长回文子串,然后公共回文子串的长度只能其中的一些公共回文子串的长度L,L-2,L-4等等,然后二分答案加hash进行判断就可以了。

但不过我还是WA了很久,我想到了奇偶回文的情况,但不过还是错了,写得不够好吧。后来我偶然想起曾经看过大佬在字符串中插入一些字符,避免奇偶回文的情况。结果还是改了很久,后来有因为数组开小了错了几发,才过了。总结这道题看似简单其实并不简单,还有很多的坑。

#include 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=100010;
char s[N<<1],ss[N<<1],s1[N],s2[N],str[N<<2];
int p[N<<2],len1,len2,tot;
ull hash1[N<<1],hash2[N<<1],po[N<<1];
ull geths1(int l,int r)
{
    if(l==0)
        return hash1[r];
    return hash1[r]-hash1[l-1]*po[r-l+1];
}
ull geths2(int l,int r)
{
    if(l==0)
        return hash2[r];
    return hash2[r]-hash2[l-1]*po[r-l+1];
}
int manacher(int len)
{
    int id=0,mx=0,m_len=0;
    for(int i=2; ii)
            p[i]=min(p[2*id-i],mx-i);
        else
            p[i]=1;
        while(str[i+p[i]]==str[i-p[i]])
            p[i]++;
        if(i+p[i]>mx)
        {
            mx=i+p[i];
            id=i;
        }
        m_len=max(m_len,p[i]-1);
    }
    return m_len;
}
unordered_mapmp;
int judge(int len)
{
    mp.clear();
    for(int i=2; i+len-1=len)
        {
            int id=i/2-1;
            mp[geths1(id-len/2,id+len/2)]=1;
        }
    }
    for(int i=0; i+len-1>1;
            if(judge(mid<<1|1))
            {
                ans=(mid<<1|1);
                l=mid+1;
            }
            else
                r=mid-1;
        }
        printf("%d\n",ans>>1);
    }
    return 0;
}

 

你可能感兴趣的:(ACM题解)