Hihocoder #1602 : 本质不同的回文子串的数量 manacher + BKDRhash
#1602 : 本质不同的回文子串的数量
描述
给定一个字符串S,请统计S的所有子串中,有多少个本质不同的回文字符串?
注意如果两个位置不同的子串满足长度相同且对应字符也都相同,则认为这两个子串本质上是相同的。
输入
一个只包含小写字母的字符串S。
对于30%的数据,S长度不超过100。
对于60%的数据,S长度不超过1000。
对于100%的数据,S长度不超过800000。
输出
回文子串的数量
- 样例输入
-
abbab
- 样例输出
5
- 题解:
- 跑manacher的时候 hash标记即可
#include <bits/stdc++.h>
inline long long read(){long long x=,f=;char ch=getchar();while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}return x*f;}
using namespace std; const long long INF = 1e14;
const int N = 1e6 + ; unsigned long long P = 10000019ULL;
unsigned long long sqr[N],has[N]; //BKDRHash,最优的字符串hash算法。hash一开始是等于0的
const int seed = ; // 31 131 1313 13131 131313 etc..
const int maxn = +;
char str[maxn];
unsigned long long sumHash[maxn]; //前缀hash值
const int MOD = ;
struct StringHash
{
int first[MOD+],num;
unsigned long long EdgeNum[maxn]; // 表明第i条边放的数字(就是sumHash那个数字)
int next[maxn],close[maxn]; //close[i]表示与第i条边所放权值相同的开始的最大位置
//就比如baba,现在枚举长度是2,开始的时候ba,close[1] = 1;表明"ba"开始最大位置是从1开始
//然后枚举到下一个ba的时候,close[1]就要变成3了,开始位置从3开始了
void init ()
{
num = ; memset (first,,sizeof first);
return ;
}
int insert (unsigned long long val,int id) //id是用来改变close[]的
{
int u = val % MOD;
for (int i = first[u]; i ; i = next[i]) //存在边不代表出现过,出现过要用val判断,val才是唯一的,边还是压缩后(%MOD)的呢
{
if (val == EdgeNum[i]) //出现过了
{
int t = close[i]; close[i] = id;//更新最大位置
return t;
}
}
++num; //没出现过的话,就加入图吧
EdgeNum[num] = val; // 这个才是精确的
close[num] = id;
next[num] = first[u];
first[u] = num;
return ;//没出现过
}
}H; char a[N];
int ans = ;
map<unsigned long long, int> mp;
void gao(int i,int j) {
unsigned long long now = has[j] - has[i-] * sqr[j-i+];
if(!H.insert(now,)) ++ans,mp[now]++;
}
int r[N];
int main() {
scanf("%s",a+);
int n = strlen(a+);
sqr[] = ;for(int i = ; i <= n; ++i) sqr[i] = sqr[i-] * P;
for(int i = ; i <= n; ++i) has[i] = has[i-] * P + a[i];
int x = , p = ;
for(int i = ; i <= n; ++i) {
int j = ;
gao(i,i);
if(p > i) j = min(r[*x-i],p-i);
while(i + j + <= n&& a[i+j+] == a[i-j-])
{
gao(i-j-,i+j+);
j++;
}
r[i] = j;
if(i+j > p) {
p = i + j;
x = i;
}
}
H.init();
x = ,p = ;
for(int i = ; i <= n; ++i) {
int j = ;
if(p > i) j = min(r[*x-i],p-i+);
while(i+j<=n && a[i+j] == a[i-j-]) {
gao(i-j-,i+j);
++j;
}
r[i] = j;
if(i+j- > p) {
p = i+j-;
x = i;
}
}
printf("%d\n",ans);
return ;
}
Hihocoder #1602 : 本质不同的回文子串的数量 manacher + BKDRhash的更多相关文章
- hiho1602本质不同的回文子串的数量
给定一个字符串S,请统计S的所有子串中,有多少个本质不同的回文字符串? 注意如果两个位置不同的子串满足长度相同且对应字符也都相同,则认为这两个子串本质上是相同的. Input 一个只包含小写字母的字符 ...
- #1589 : 回文子串的数量(Manacher)
#1589 : 回文子串的数量 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个字符串S,请统计S的所有|S| * (|S| + 1) / 2个子串中(首尾位置不 ...
- 【HIHOCODER 1589】回文子串的数量(Manacher)
描述 给定一个字符串S,请统计S的所有|S| * (|S| + 1) / 2个子串中(首尾位置不同就算作不同的子串),有多少个是回文字符串? 输入 一个只包含小写字母的字符串S. 对于30%的数据,S ...
- 1089 最长回文子串 V2(Manacher算法)
1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 回文串是指aba.abba.cccbccc.aaaa ...
- 51Nod 1089:最长回文子串 V2(Manacher算法)
1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 回文串是指aba.abba.cccbccc.aaa ...
- 51NOD 1088 最长回文子串&1089 最长回文子串 V2(Manacher算法)
回文串是指aba.abba.cccbccc.aaaa这种左右对称的字符串. 输入一个字符串Str,输出Str里最长回文子串的长度. Input 输入Str(Str的长度 <= 1000(第二题要 ...
- [51Nod1089] 最长回文子串 V2(Manacher算法)
1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 回文串是指aba.abba.cccbccc.aaaa这种左右对称 ...
- hdu5371 最长回文子串变形(Manacher算法)
pid=5371">http://acm.hdu.edu.cn/showproblem.php? pid=5371 Problem Description Hotaru Ichijou ...
- 【回文字符串】 最长回文子串O(N) Manacher算法
原理讲的清晰:Manacher's ALGORITHM: O(n)时间求字符串的最长回文子串 注意: ①动态生命P[]和newStr数组后,不要忘记delete[] //其实这是基本的编码习惯 ②最终 ...
随机推荐
- android实现多条件筛选列表菜单筛选菜单
封装组合控件实现一个简单的多条件筛选菜单,可根据自己需求定制筛选条件,动态添加筛选项,灵活使用. 控件封装,点击切换,使用popupWindow实现下拉列表,项目中封装了多种数组数据排序处理方法的工具 ...
- APACHE 配置虚拟主机和HTTPS
prepare the running env of os make sure you are using redhat or centen os 7.5 cat /etc/redhat-releas ...
- JMeter部分功能详解
JMeter 介绍: 一个非常优秀的开源免费的性能测试工具. 优点:你用着用着就会发现它的重多优点,当然不足点也会呈现出来. 从性能工具的原理划分: Jmeter工具和其他性能工具在原理上完全一致,工 ...
- OS | 死锁
死锁的四个条件 互斥 占用等待 非剥夺 循环等待 死锁的解决方案 死锁预防 间接预防:防止前三个条件中的任何一个的发生 直接预防:防止循环等待的发生 死锁避免 进程启动拒绝:不启动任何一个可能发生死锁 ...
- Find Median from Data Stream - LeetCode
Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...
- ios6.0 siri语音识别
Siri 让你能够利用语音来完成发送信息.安排会议.拨打电话等更多事务* .只需像平常一样讲话,就能让 Siri 帮你做事.你会发现 Siri 是如此易用而且能干,精彩用法越用你会发现越多. 懂你所说 ...
- ubuntu 配置L2tp出现的问题解决
运行环境:ubuntu 14.04 64位 配置推荐网址: https://linux.cn/article-3409-1.html 首先,官方教程是必须的: https://help.ubuntu. ...
- nginx +uwsgi + django配置
一 安装 nginx 二 安装 uwsgi ,pip install uwsgi 三 配置nginx 打开 nginx.conf文件, location / { # root html; # ind ...
- JSON API:用 JSON 构建 API 的标准指南中文版
译文地址:https://github.com/justjavac/json-api-zh_CN 假设你和你的团队以前争论过使用什么方式构建合理 JSON 响应格式, 那么 JSON API 就是你的 ...
- 手动编译高速扫描器MasScan
常见的端口扫描器有NMAP,ZMAP,superScan等,我们使用后各有千秋,ZMAP号称44分钟扫全球ip,那么有没有比ZMAP更快的端口扫描器呢,今天我们来研究下masscan,这款扫描器号称3 ...