Codeforces 1326 D. Prefix-Suffix Palindrome

在这里插入图片描述

题意:

给你一个字符串 s s s,找出最长的满足以下条件的字符串 s s s

  • 长度不超过 s s s
  • s s s为回文字符串
  • 存在两个字符串 a a a b b b (可能为空), s = a + b s=a+b s=a+b a a a s s s 的前缀, a a a s s s 的后缀)

先求出前缀和后缀,先把匹配的前后缀长度 t t t 求出来,然后由 t − 1 t-1 t1 开始从左向右匹配 h a s h hash hash 值求最长的回文串,由 n − t n-t nt 开始从左向右匹配 h a s h hash hash 值求最长的回文串。
c f cf cf h a s h hash hash 一定要注意 b a s e base base m o d mod mod ,不然特别容易被卡。

AC代码:

const int N = 1000100;
const ull P = 13131;
const int mod = 1000000007;
char s[N];
ull power[N];
ull pre[N], suf[N];
int ans, n;
int t, res, tmp;

ull hash1(int l, int r)
{
    return (pre[r] - pre[l - 1] * power[r - l + 1] % mod + mod) % mod;
}

ull hash2(int l, int r)
{
    return (suf[l] - suf[r + 1] * power[r - l + 1] % mod + mod) % mod;
}

void init()
{
    power[0] = 1;
    rep(i, 1, 1000000)
        power[i] = power[i - 1] * P % mod;
}

int main()
{
    init();
    int T;
    sd(T);
    while (T--)
    {
        ans = 0;
        ss(s + 1);
        n = strlen(s + 1);
        pre[0] = 0;
        suf[n + 1] = 0;
        rep(i, 1, n)
        {
            pre[i] = (pre[i - 1] * P + (s[i] - 'a' + 1)) % mod;
        }
        per(i, n, 1)
        {
            suf[i] = (suf[i + 1] * P + (s[i] - 'a' + 1)) % mod;
        }
        t = 0;
        res = 0;
        tmp = 0;
        while (s[t + 1] == s[n - t] && t + 1 < n - t)
            t++;
        rep(i, t + 1, n - t)
        {
            if (hash1(t + 1, i) == hash2(t + 1, i) && i - t > res)
            {
                res = i - t;
                tmp = 0;
            }
        }
        per(i, n - t, t + 1)
        {
            if (hash1(i, n - t) == hash2(i, n - t) && n - t - i + 1 > res)
            {
                res = n - t - i + 1;
                tmp = 1;
            }
        }
        rep(i, 1, t)
        {
            cout << s[i];
        }
        if (tmp == 0)
        {
            rep(i, t + 1, t + res)
            {
                cout << s[i];
            }
        }
        else
        {
            per(i, n - t, n - t - res + 1)
            {
                cout << s[i];
            }
        }
        rep(i, n - t + 1, n)
        {
            cout << s[i];
        }
        cout << '\n';
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值