多校#5-1005-Instring-HDU5785-manacher+维护
寻找三元组(i,j,k),使得(i,j)(j,k)都是回文字串,其中i<=j<k.
可以发现,对于每一位i,只要预处理出来有多少个以i为右端的回文串和以i为左端的回文串。把那些串的另一端的坐标和计算出来就可以了。
然后ans = ∑cntR[i]*cntL[i+1]
这里cntR[i]记录以i为右端的回文串的左端坐标和。cntL[i]同理。
然后这道题的数据范围是1e6,多case。必须要O(n)才能过。
首先用O(n)的Manacher处理每一位的回文半径,之后遍历处理
可以发现这里需要O(n)复杂度给指定区间加上一个等差序列。于是开几个数组维护,空间换时间。
用cnt_add记录加了多少次,add记录首项加了多少,这样从首项往后递推,每次add[i+1] = add[i]-cnt_add[i] cnt_add[i+1] += cnt_add[i] cntL[i] += add[i]
这样可以从首项更新到字符串尾。但是我们要更新一段值,就有一段多加了,于是就再开一个mns记录多加的的值.
比如要更新[l,r] 那么就给mns[r+1]置为add[r+1]时的值。这样就可以把多加的抵消了。同时也要维护一个cnt_mns记录次数。
最后还要注意分回文长度奇偶讨论。
//坑了好久的题。最开始想到了用树状数组维护cnt,成段更新,然而卡log。
1 #include <cstdio> 2 #include <ctype.h> 3 #include <cstring> 4 #include <algorithm> 5 6 #define LL long long 7 #define lson rt<<1,l,mid 8 #define rson rt<<1|1,mid+1,r 9 #define root 1,N,1 10 using namespace std; 11 12 const int maxn = 1e6+100; 13 const LL MOD = 1e9+7; 14 15 char Ma[2*maxn]; 16 int Mp[2*maxn]; 17 void update(LL &x,LL d) 18 { 19 x += d; 20 if(x >= MOD) x -= MOD; 21 if(x < 0) x += MOD; 22 } 23 24 void Manacher(char s[],int len) 25 { 26 memset(Mp,0,sizeof Mp); 27 int l = 0; 28 Ma[l++] = '$'; 29 Ma[l++] = '#'; 30 for(int i=0;i<len;i++) 31 { 32 Ma[l++] = s[i]; 33 Ma[l++] = '#'; 34 } 35 Ma[l] = 0; 36 int mx = 0,id = 0; 37 for(int i=0;i<l;i++) 38 { 39 Mp[i] = mx > i ? min(Mp[2*id-i],mx-i) : 1; 40 while(Ma[i+Mp[i]] == Ma[i-Mp[i]] ) Mp[i]++; 41 if(i + Mp[i] > mx) 42 { 43 mx = i+Mp[i]; 44 id = i; 45 } 46 } 47 } 48 49 char line[maxn]; 50 int p[maxn]; 51 LL cntL[maxn],cntR[maxn]; 52 LL add[maxn],mns[maxn]; 53 LL cnt_add[maxn],cnt_mns[maxn]; 54 55 void init() 56 { 57 memset(cnt_mns,0,sizeof cnt_mns); 58 memset(cnt_add,0,sizeof cnt_add); 59 memset(add,0,sizeof add); 60 memset(mns,0,sizeof mns); 61 } 62 63 LL ans = 0; 64 void solve(int len) 65 { 66 init(); 67 for(int i=2;i<2*len+1;i++) 68 { 69 int tmp = Mp[i]; 70 if(Ma[i] == '#') 71 { 72 int cur = i/2+1,L = (i-tmp)/2+1, R = (i+tmp)/2-1,r = (tmp-1)/2; 73 update(add[L],R); 74 update(mns[cur],R-r); 75 cnt_add[L] ++; 76 cnt_mns[cur]++; 77 }else 78 { 79 int cur = i/2,L = (i-tmp)/2+1, R = (i+tmp)/2-1,r = 1+(tmp-1)/2; 80 update(add[L],R); 81 update(mns[cur+1],R-r); 82 cnt_add[L] ++; 83 cnt_mns[cur+1]++; 84 } 85 } 86 for(int i=1;i<=len;i++) 87 { 88 update(cntL[i],add[i]-mns[i]); 89 update(add[i+1],add[i]-cnt_add[i]); 90 update(mns[i+1],mns[i]-cnt_mns[i]); 91 update(cnt_add[i+1],cnt_add[i]); 92 update(cnt_mns[i+1],cnt_mns[i]); 93 } 94 95 init(); 96 for(int i=2;i<2*len+1;i++) 97 { 98 int tmp = Mp[i]; 99 if(Ma[i] == '#') 100 { 101 int cur = i/2+1,L = (i-tmp)/2+1, R = (i+tmp)/2-1,r = (tmp-1)/2; 102 add[cur] += cur-1; 103 mns[R+1] += cur - r - 1; 104 cnt_add[cur] ++; 105 cnt_mns[R+1] ++; 106 }else 107 { 108 int cur = i/2,L = (i-tmp)/2+1, R = (i+tmp)/2-1,r = 1+(tmp-1)/2; 109 add[cur] += cur; 110 mns[R+1] += cur-r; 111 cnt_add[cur] ++; 112 cnt_mns[R+1] ++; 113 } 114 } 115 for(int i=1;i<=len;i++) 116 { 117 update(cntR[i],add[i]-mns[i]); 118 update(add[i+1],add[i]-cnt_add[i]); 119 update(mns[i+1],mns[i]-cnt_mns[i]); 120 update(cnt_add[i+1],cnt_add[i]); 121 update(cnt_mns[i+1],cnt_mns[i]); 122 } 123 ans = 0; 124 for(int i=1;i<=len;i++) 125 { 126 update(ans,(cntR[i]*cntL[i+1])%MOD); 127 } 128 } 129 130 int main() 131 { 132 //freopen("1005.in","r",stdin); 133 while(true) 134 { 135 char c; 136 int len = 0; 137 while((c = getchar()) && isalpha(c)) 138 { 139 line[len++] = c; 140 } 141 if(c == EOF) break; 142 Manacher(line,len); 143 144 memset(cntL,0,sizeof cntL); 145 memset(cntR,0,sizeof cntR); 146 solve(len); 147 printf("%I64d\n",(ans+MOD) % MOD); 148 } 149 }
转载于:https://www.cnblogs.com/helica/p/5742588.html
多校#5-1005-Instring-HDU5785-manacher+维护相关推荐
- 计算机组装与维护校本教材,《计算机组装及维护》校本教材.pdf
[摘要]国家中等职业教育改革发展示范学校建设项目校本教材 计算机组装与维护 (修订稿) 主 编:李晓 副主编:永乾 安宁市职业高级中学 <计算机组装与维护>课程简介 作为职高学校的计算机专 ...
- 计算机信息管理面试自我介绍,信息管理专业的面试自我介绍
在毕业的时候我们通常会要求写一份自我评价或自我鉴定,这些会放入自己的档案中,所以不能够随便写写,管理专业的自我评价范文,供参考. 大学四年中,我各方面的能力都得到了发展,可以说,经过大学四年的学习,我 ...
- 大学生计算机面试,大学生计算机毕业面试自我介绍
大学生计算机毕业面试自我介绍 发布时间:2020-02-26 计算机专业在目前是比较需要的,那么你会自我介绍了吗,今天小编就给大家来分享一下面试自我介绍,好好参考哦 计算机专业应届生面试自我介绍 我学 ...
- 计算机如何自我介绍教程,2020计算机专业自我介绍4篇
<2020计算机专业自我介绍4篇>由会员分享,可在线阅读,更多相关<2020计算机专业自我介绍4篇(6页珍藏版)>请在人人文库网上搜索. 1.2020计算机专业自我介绍4篇本文 ...
- android开发电话面试自我介绍,安卓开发面试自我介绍
面试自我介绍既是面试中必备环节,也是求职者们最关心的问题之一.一个常规的面试,寒暄之后面试官提出的第一个问题几乎千篇一律:"请您简单地做一下自我介绍".有些被面试者都会问:简历中情 ...
- 计算机教师面试1分钟自我介绍视频,学校面试1分钟自我介绍
在学校当中有时候也是进行面试的,我们在面试的时候是如何进行自我介绍的呢?以下是小编给大家整理的学校面试1分钟自我介绍,喜欢的过来一起分享吧. 学校面试1分钟自我介绍一 时光匆匆,转眼间,大学三年的美丽 ...
- 计算机应聘大学生自我介绍,大学生计算机毕业面试自我介绍
计算机专业在目前是比较需要的,那么你会自我介绍了吗,今天小编就给大家来分享一下面试自我介绍,好好参考哦 计算机专业应届生面试自我介绍 我学习成绩优良,学风端正,学习刻苦努力,奋发向上.在认真完成自身学 ...
- 我的计算机专业作文,计算机专业自我介绍
计算机专业自我介绍 发布时间:2021-01-07 [计算机专业自我介绍一] 大学四年中,我各方面的能力都得到了发展,可以说,经过大学四年的学习,我已经具备了适应社会工作的能力.这学期即将画上了句号, ...
- 面试时计算机工程自我介绍范文,计算机专业大学生面试自我介绍范文
<计算机专业大学生面试自我介绍范文>由会员分享,可在线阅读,更多相关<计算机专业大学生面试自我介绍范文(5页珍藏版)>请在人人文库网上搜索. 1.计算机专业大学生面试自我介绍范 ...
最新文章
- 最新调查,48%的美国人表示不会乘坐自动驾驶汽车
- torch.tensordot()介绍
- php long2ip,php ip2long和long2ip函数实现
- [Java并发编程实战] 共享对象之可见性
- ML之Hash_HamMingDistance:基于输入图片哈希化(均值哈希+差值哈希)即8*8个元素的单向vector利用汉明距离算法进行判别
- 神策 FM | 关于定价的 10 年经验总结
- c语言基础回顾 —— 其他知识点
- UITextView
- 关于python开发CRM系统
- bzoj2437 [Noi2011]兔兔与蛋蛋
- python入门代码大全-python入门代码指南教程书籍推荐2020总结全集汇总
- 时间序列深度学习:状态 LSTM 模型预测太阳黑子(一)
- [C/C++11语法]_[0基础]_[lamba 表达式介绍]
- 制作自启动的MSDN简体中文版和英文版win98ISO镜像
- IGS发布RINEX 4.00
- ENVI用ROI进行裁剪
- 虚拟机设置共享文件夹之后看不见文件(失败合集+成功分享)
- 2022软件测试技能 Apache JMeter 性能测试从入门到精通
- Android开发之小程序-秒表
- oracle 帮助文件,oracle chm帮助文件下载
热门文章
- 从DOM到虚拟DOM——前端DOM发展史、性能与产能双赢背后的思考
- 学历影响程序员的工资吗?
- 关于TCP三次握手过程
- linux统计某个字符个数,Linux统计一个文件中特定字符个数的方法
- 测控技术与仪器专业c语言教学视频,测控技术与仪器要学哪些基础和专业课程...
- android 宽度动画,android – ObjectAnimator对LinearLayout宽度进行动画处理
- android 查找所有dialog_android 布局文件layout分组的简单使用
- 基本Linux命令的用法
- Python风格总结:面向对象
- 吴恩达深度学习5.2笔记_Sequence Models_自然语言处理与词嵌入