CodeForces 7D Palindrome Degree

字符串hash。首先说下需要注意的地方:当对Mod取余时,可能造成本不相同的,取余结束之后相同了。

此时应对多个不同的Mod取余,多次计算只能说降低上述情况的发生。感觉正式比赛中不会有这种题,比较拼RP。

比如此题,Mod = 2^32,可以,Mod = 2^64,WA了。。。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <ctime>
#include <iomanip>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-6)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 1000000007

using namespace std;

const int MAXN = 5000010;

char s[MAXN];

ULL e = 256;

ULL pre[MAXN],suf[MAXN];
ULL p1[MAXN],s1[MAXN];

LL K[MAXN];

int main()
{
    scanf("%s",s+1);

    int i,n = strlen(s+1);

    for(i = 1,pre[0] = 0;i <= n; ++i)
        pre[i] = pre[i-1]*e + s[i];

    for(i = 2,suf[1] = s[1];i <= n; ++i)
        suf[i] = suf[i-1] + s[i]*e,e *= 256;

    e = 256;

    for(i = 1,p1[0] = 0;i <= n; ++i)
    {
        p1[i] = p1[i-1]*e + s[i];
        p1[i] %= Mod;
    }
    for(i = 2,s1[1] = s[1];i <= n; ++i)
    {
        s1[i] = s1[i-1] + s[i]*e,e *= 256;
        e %= Mod,s1[i] %= Mod;
    }
    K[0] = 0;

    for(K[0] = 0,i = 1;i <= n; ++i)
    {
        if(pre[i] == suf[i] && p1[i] == s1[i])
            K[i] = K[i/2] + 1;
        else
            K[i] = 0;
    }

    LL ans = 0;
    for(i = 1;i <= n; ++i)
        ans += K[i];

    printf("%I64d\n",ans);
    return 0;
}
时间: 2024-08-06 19:58:54

CodeForces 7D Palindrome Degree的相关文章

CodeForces 7D Palindrome Degree 字符串hash

题目链接:点击打开链接 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h> #include<queue> #include<string> #include<stdlib.h> #include<a

Codeforces Beta Round #7--D. Palindrome Degree(Manacer)

题目:http://blog.csdn.net/winddreams/article/details/44218961 求出每一个点为中心的最长字符串,推断该串是不是从开头的回文串. #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; int p[12000000] , dp[6000000]; char s[12000000] , str[12000000] ;

Codeforces 486C Palindrome Transformation(贪心)

题目链接:Codeforces 486C Palindrome Transformation 题目大意:给定一个字符串,长度N,指针位置P,问说最少花多少步将字符串变成回文串. 解题思路:其实只要是对称位置不相同的,那么指针肯定要先移动到这里,修改字符只需要考虑两种方向哪种更优即 可.然后将所有需要到达的位置跳出来,贪心处理. #include <cstdio> #include <cstring> #include <cstdlib> #include <vec

Palindrome Degree题解

Palindrome Degree题解 其实是道水题, 但是我太弱了!!! 开始想着如何判断后缀是回文, 屈辱看题解后发现, 只要判断前缀,然后判断后缀的反向是否与前缀相等即可, 但是我居然将kmp与回文弄混了,直接判前后缀相不相等, 太弱了!!败犬的哀嚎 #include<bits/stdc++.h> #define ull unsigned long long using namespace std; const int N=5e6+7; int n,t,f[N],ans=0; ull b

Palindrome Degree(CodeForces 7D)—— hash求回文

学了kmp之后又学了hash来搞字符串.这东西很巧妙,且听娓娓道来. 这题的题意是:一个字符串如果是回文的,那么k值加1,如果前一半的串也是回文,k值再加1,以此类推,算出其k值.打个比方abaaba,k值为3,abaxxaba,k值为1.现在,给出一个串,让你求这个串的所有前缀(包括本身)的k值的和. 如果考虑马拉车,那么先预处理出每个地方的最长回文长度,然后不断的截断,如果子串的回文长度大于其回文长度,那么k值加1,这样即可.但是马拉车写起来比较繁琐,没有模板我也没法手写. 这里提供hash

Codeforces 159D Palindrome pairs

http://codeforces.com/problemset/problem/159/D 题目大意: 给出一个字符串,求取这个字符串中互相不覆盖的两个回文子串的对数. 思路:num[i]代表左端点在i这个位置的回文串个数,然后用树状数组维护sum[i],代表回文串右端点小于等于i的回文串数,总复杂度:O(n^2) 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstr

Codeforces 932G Palindrome Partition - 回文树 - 动态规划

题目传送门 通往???的传送点 通往神秘地带的传送点 通往未知地带的传送点 题目大意 给定一个串$s$,要求将$s$划分为$t_{1}t_{2}\cdots t_{k}$,其中$2\mid k$,且$t_{i} = t_{k - i}$,问方案数. 直接做不太好做.虽然可以$O(n^{2})$进行动态规划. 考虑做一步转化:设$s' = s_{1}s_{n}s_{2}s_{n - 1}\cdots s_{n / 2}s_{n / 2 + 1}$. 然后它的一个偶回文划分可以和原来的划分一一对应.

CodeForces 486C Palindrome Transformation

题意: n(10^5)个字符  光标停在第pos个字符上  光标可以左右任意移动  而且可以从最左移到最右也可以从最右移到最左  在光标处的字符可以按字母顺序或倒序更改  更改也可以a->z或者z->a  光标移动和字符更改都需要1s  问最短几s能把串变成回文的 思路: 最后的状态是一定的  因此更改的次数和策略无关  扫一遍就可以知道更改最少需要几s 光标移动需要一定的策略  容易想到最优的方法一定是在字符串的一半移动  因此记录在字符串左一半和右一半最远的不回文的位置  让光标移动就好了

codeforces 1045I Palindrome Pairs 【stl+构造】

题目:戳这里 题意:给1e5个字符串,问有多少对字符串组合,满足最多只有一种字符有奇数个. 解题思路:每种情况用map存一下就行了.感觉这题自己的代码思路比较清晰,所以写个题解记录一下 附ac代码: 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 2e5 + 10; 5 const ll mod = 998244353; 6 int arr[33]; 7 i