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

  学了kmp之后又学了hash来搞字符串。这东西很巧妙,且听娓娓道来。

  这题的题意是:一个字符串如果是回文的,那么k值加1,如果前一半的串也是回文,k值再加1,以此类推,算出其k值。打个比方abaaba,k值为3,abaxxaba,k值为1。现在,给出一个串,让你求这个串的所有前缀(包括本身)的k值的和。

  如果考虑马拉车,那么先预处理出每个地方的最长回文长度,然后不断的截断,如果子串的回文长度大于其回文长度,那么k值加1,这样即可。但是马拉车写起来比较繁琐,没有模板我也没法手写。

  这里提供hash的方法。hash的方法就是给出一个素数,我这里是使用的17,然后就把字符串当做17进制,把每个位置的值和反过来计算的这个位置的值计算出来,然后每位一比对,如果相同,就在此处回文(显然,复杂度是O(n))。不过我觉得17可能不妥,因为s[i]的上限值是127,那么这个素数应当大于127才好,这里先暂时这样吧,如果不行就换233好了- 。-

  这东西怎么理解呢,打个比方121,在10进制看来从左往右的值和从右往左的值相同,那么它回文。

  具体见代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <set>
 5 #include <iostream>
 6 using namespace std;
 7 typedef pair<int,int> pii;
 8 typedef unsigned long long ull;
 9 typedef long long ll;
10
11 const int bas = 17;
12 const int N = 5*(int)1e6+5;
13
14 char s[N];
15 int dp[N];
16
17 int main()
18 {
19     scanf("%s",s+1);
20     ull pre = s[1], suf = s[1], mul = 1;
21     int len = strlen(s+1);
22     ll ans = 1;
23     dp[1]=1;
24
25     for(int i=2;i<=len;i++)
26     {
27         mul *= bas;
28         pre = pre + s[i] * mul;
29         suf = suf * bas + s[i];
30         if(pre == suf) dp[i] = dp[i>>1] + 1;
31         ans += (ll)dp[i];
32     }
33     printf("%I64d\n",ans);
34     return 0;
35 }
时间: 2024-12-26 17:50:41

Palindrome Degree(CodeForces 7D)—— hash求回文的相关文章

Palindrome - URAL - 1297(求回文串)

题目大意:RT 分析:后缀数组求回文串,不得不说确实比较麻烦,尤其是再用线段数进行查询,需要注意的细节地方比较多,比赛实用性不高......不过练练手还是可以的. 线段数+后缀数组代码如下: =========================================================================================================================================== #include<stdio

马拉车,O(n)求回文串

body { font-family: sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10px; padding-bottom: 10px; background-color: white; padding: 30px } body>*:first-child { margin-top: 0 !important } body>*:last-child { margin-bottom: 0 !important } a

HDU 5371(2015多校7)-Hotaru&#39;s problem(Manacher算法求回文串)

题目地址:HDU 5371 题意:给你一个具有n个元素的整数序列,问你是否存在这样一个子序列,该子序列分为三部分,第一部分与第三部分相同,第一部分与第二部分对称,如果存在求最长的符合这种条件的序列. 思路:用Manacher算法来处理回文串的长度,记录下以每一个-1(Manacher算法的插入)为中心的最大回文串的长度.然后从最大的开始穷举,只要p[i]-1即能得出以数字为中心的最大回文串的长度,然后找到右边对应的'-1',判断p[i]是不是大于所穷举的长度,如果当前的满足三段,那么就跳出,继续

马拉车算法——求回文子串个数zoj4110

zoj的测评姬好能卡时间.. 求回文子串的个数:只要把p[i]/2就行了: 如果s_new[i]是‘#’,算的是没有中心的偶回文串 反之是奇回文串 /* 给定两个字符串s,t 结论:s,t不相同的第一个字符下标为l,最后一个字符下标为r 如果l==r,那么不存在解 如果l<r,那么翻转s的一个子串时,一定是将s[l]和s[r]互相翻转 反证:假设存在s[l]和s[r+k]的翻转方法, 因为s[r+k]=t[r+k]=t[l],且s[l]=t[r+k],可得s[l]=t[l],矛盾 l-k同理 所

Codeforces Round #427 (Div. 2) D. Palindromic characteristics(Manacher求回文串)

题目链接:Codeforces Round #427 (Div. 2) D. Palindromic characteristics 题意: 给你一个串,定义k-th回文串,让你求每个k-th的数量. 题解: manacher处理好后做一下dp就行了. 当然也可以直接dp不用manacher. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 cons

HDU 1513 Palindrome 求回文串

这个题是走弯路了,刚开始自己DP出了方程,无限MLE,唉 if(s1[i]==s1[j]) dp[i][j]=dp[i+1][j-1]; else dp[i][j]=min(dp[i][j-1],dp[i+1][j]) +1; 后来百度了一下,这个原来是个经典回文串问题,即先将串置反,然后求LCS........ 然后就是这题卡时间卡的特别厉害,多用了一次strlen就TLE AC: #include<cstdio> #include<string> #include<str

Extend to Palindrome (顺序Hash和逆序Hash处理回文)

题目链接:https://vjudge.net/contest/344930#problem/E 题目大意:给出一个字符串,在末尾补充最少的字母,使其整个成为一个回文串 题目思路:对字符串进行顺序Hash和逆序Hash,然后去枚举位置,如果此时顺序的Hash和逆序的Hash值想等就说明此时是一个回文串.然后就直接输出该回文串前面的部分,再输出该回文串.如果没有回文串,那么就使整个字符串成为回文串 1 #include <stdio.h> 2 #include <algorithm>

HDU 4632 Palindrome subsequence(区间DP求回文子序列数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4632 题目大意:给你若干个字符串,回答每个字符串有多少个回文子序列(可以不连续的子串).解题思路: 设dp[i][j]为[i,j]的回文子序列数,那么得到状态转移方程: dp[i][j]=(dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+MOD)%MOD if(str[i]==str[j]) dp[i][j]+=dp[i-1][j+1]+1 代码: 1 #include<cst

[加强版] Codeforces 835D Palindromic characteristics (回文自动机、DP)

题目链接: https://codeforces.com/contest/835/problem/D 题意: 一个回文串是\(1\)-回文的,如果一个回文串的左半部分和右半部分一样且都是\(k\)-回文串(右半部分是指长度为该串长度除以二下取整的后缀),则该串为\((k+1)\)回文串,满足该串是\(k\)回文串的最大\(k\)称作该串的回文级别.给定一个串\(s\), 对于每一个\(k=1,2,...,n\)求出该串中有多少个位置不同的\(k\)-回文串.\(n\le 5\times 10^6