codeforces 7d hash

题意:长度是 n 的字符串 s,如果它自身是回文数,且它的长度为  floor(n / 2)的前缀和后缀是 (k - 1)-回文数,则它被称作 k-回文数。按照定义,任何字符串 (甚至空字符串) 都是 0-回文数。

字符串 s 的回文度,被定义为这样的一个最大数 k,满足 s 是 k-回文数。例如,"abaaba" 具有的回文度是 3 。

给定一个字符串。您的任务是,找出它的全部前缀的回文度之和。

题解:dp,如果长度为i的前后缀是回文数,那么dp[i] = dp[i >> 1] + 1

那么需要解决的就是如何判断是否是回文,可以hash。

hash,只要完成一个双射即可,这就要求“基数”是质数,从左往右加和从右往左加类比数字的进位

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ULL;
const int maxn = 5e6 + 10;

char str[maxn];
int dp[maxn];
ULL f1[maxn], f2[maxn];
int main(){
    scanf("%s", str + 1);
    int l = strlen(str + 1);
    ULL dig = 1;
    ULL sum = 0;
    dp[0] = 0;
    for(int i = 1 ; i <= l; i ++){
        if(str[i] >= '0' && str[i] <= '9'){
            str[i] = str[i] - '0';
        }else if(str[i] >= 'a' && str[i] <= 'z'){
            str[i] = str[i] - 'a' + 10;
        }else{
            str[i] = str[i] - 'A' + 36;
        }
        f1[i] = f1[i - 1] * 131 + str[i];
        f2[i] = (f2[i - 1] + str[i] * dig);
        dig *= 131;
        if(f1[i] == f2[i]){
            dp[i] = dp[i >> 1] + 1;
            sum += dp[i];
        }
    }
    cout << sum << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/86529707