【2018.07.28】(字符串/回文串)学习Manacher算法小记
主要是应用在回文串啦,原理也理解了老半天,如果没有图片的话,我也看不太懂它的原理
学习的灵感来源来自于:https://segmentfault.com/a/1190000008484167
- /* 最长回文 */
- /*给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
- 回文就是正反读都是一样的字符串,如aba, abba等
- Input
- 输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
- 两组case之间由空行隔开(该空行不用处理)
- 字符串长度len <= 110000
- Output
- 每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
- Sample Input
- aaaa
- abab
- Sample Output
- 4
- 3*/
- #include <algorithm>
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <cmath>
- using namespace std;
- /*说实话我非常讨厌字符串的题目,对于我来说可能是会在输入出现问题,所以我一直都不
- 太喜欢字符串,拿到这道题是没有什么思路的。但是简单看了解析就不得不佩服他们的想法
- 他的想法是,在每个字符串之间加入特殊符号,他用的是#,这样子就可以算出奇数个的回
- 文串了,这样奇数字符串就仍然以字母为中心,偶数字符串就会以#为中心展开,接下来的
- 方法我还没看,但我可以猜测如果是检索到#的话就隔项去检索字母,如果是检索到字母就
- 隔项去检索字母,试着去完成一下吧*/
- //果然还是以失败告终,我去看看网上的思路吧
- char s[], ss[];
- int Count[];
- int judge( int len )
- {
- Count[]=;//最低限度是1,但这个点应该用不到的说= =,这句话应该可以删掉
- int mx=,id=;
- //mx 代表以 id 为中心的最长回文的右边界
- for(int i= ; i<=len ; i++ ) //从第一个#开始
- {
- if( mx>i )//如果这个点包含在右边界之中
- {
- Count[i] = min( Count[*id-i] , mx-i );
- /*这句话简直太精辟了,在id的右边的点i,会等于id左边点的对称点,如果
- 这个i点到id的点的距离(左段)和i点到mx点的距离(右段)相比,如果右边
- 比较小,那么就会继续向mx外部检索,如果对称点的Count[2*id-i]还不及边
- 界,那么就不必继续向外检索了,下面的循环第一步就会停止了*/
- }
- else
- {
- Count[i] = ;//如果这个点超出了右边界,那么这个点开始重新计算
- }
- while( i+Count[i]<=len && ss[i-Count[i]]==ss[ i+Count[i] ] )
- Count[i]++;//如果旁边只要有一次相等便会+1,直到不相等为止
- if( Count[i]+i > mx )//如果新检索的位置超出了最大边界
- {
- mx=Count[i]+i;//Count存储的是半径,i是当前位置,相加得新的右边界
- id=i;//id记录的是对称点所在位置
- }
- }
- //数据验证
- /*for (int i=1 ; i<=len ; i++ )
- {
- cout<<Count[i]<<' ';
- }
- cout<<endl;*/
- int max=;
- for(int i=;i<=len;i++)
- {
- if( Count[i] > max ) max=Count[i];
- }
- return max-;
- }
- int main(void)
- {
- int result;
- int j, len, i;
- ss[]='$';
- ss[]='#';
- while ( scanf("%s",s)!=EOF )
- {
- j=;
- len=strlen(s);
- for ( i= ; i<len ; i++ )
- {
- ss[j++]=s[i];
- ss[j++]='#';//执行完语句j才会自增1
- }
- //ss[j]='^';
- //printf("%s\n",ss);
- result = judge(j);
- printf("%d\n",result);
- }
- return ;
- }
- //下面这里是自己实现的代码,貌似不太行23333
- /*int judge( int len )
- {
- len=(len+1)*2+1;//比ss多一个数字,是小于
- int max=0, i=3 , count=1;
- while ( i<len )
- {
- if ( ss[i]=='#' )
- {
- while ( 1 )
- {
- if ( (i-count*2+1)>=0 || (i+count*2-1)>=len ) break;
- if ( ss[i-count*2+1] == ss[i+count*2-1] )
- {
- if ( count > max ) max=count;
- count++;
- }
- else
- {
- count=1;
- break;
- }
- }
- }
- else
- {
- while ( 1 )
- {
- if ( ss[i+count*2] == ss[i-count*2])
- {
- if ( count > max ) max=count;
- count++;
- }
- else
- {
- count=1;
- break;
- }
- if ( (i-count*2)>=0 || (i+count*2)>=len ) break;
- }
- }
- i++;
- }
- return max;
- }*/
吉哥系列故事——完美队形II
假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形:
1、挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的;
2、左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意;
3、从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则H[1] <= H[2] <= H[3] .... <= H[mid]。
现在吉哥想知道:最多能选出多少人组成新的完美队形呢?
Input 输入数据第一行包含一个整数T,表示总共有T组测试数据(T <= 20);
每组数据首先是一个整数n(1 <= n <= 100000),表示原先队形的人数,接下来一行输入n个整数,表示原队形从左到右站的人的身高(50 <= h <= 250,不排除特别矮小和高大的)。Output 请输出能组成完美队形的最多人数,每组输出占一行。Sample Input
- 2
- 3
- 51 52 51
- 4
- 51 52 52 51
Sample Output
- 3
- 4
- #include <algorithm>
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <vector>
- #include <cmath>
- #include <stack>
- #include <queue>
- using namespace std;
- #define MAXN 100010*2
- /*这题我知道是运用马拉车算法*/
- /*在manacher算法上要加上对身高的判断,中间的人身高会比较高*/
- /*检查BUG检查了好久好久= =,最后发现只要在那个地方加入一条判断就可以了= =*/
- int a[MAXN], b[MAXN], p[MAXN];
- int manacher(int len)
- {
- int mx=, id=, i, j;
- for ( i= ; i<=len ; i++ )
- {
- if ( mx > i )
- {
- p[i]=min( p[*id-i] , mx-i );
- }
- else p[i]=;
- while ( i+p[i] <= len && b[ i-p[i] ] == b[ i+p[i] ] && b[i-p[i]]<=b[i-p[i]+] )
- {//加入的条件就是上面最后一个条件
- /*if ( i%1 )
- {
- if ( b[i+1] < b[ i+1+p[i]*2 ] ) break;
- }
- else
- {
- if ( b[i] < b[ i+p[i]*2 ] ) break;
- }*/
- p[i]++;
- }
- if ( p[i]+i > mx )
- {
- mx=p[i]+i;
- id=i;
- }
- }
- int Max=;
- for ( j= ; j<=len+ ; j++ )
- {
- if ( Max < p[j] ) Max=p[j];
- }
- return Max-;
- }
- int main(void)
- {
- int repeat, i, n, temp, j;
- scanf("%d", &repeat);
- while ( repeat-- )
- {
- memset( b , , sizeof(b) );
- scanf("%d" ,&n);
- b[]=-;
- for ( i=, j= ; i<n ; i++ )
- {
- scanf("%d", &a[i] );
- b[j++]=a[i];
- b[j++]=-;
- }
- b[j]=-;
- /*for ( i=0 ; i<=j ; i++ )
- {
- printf("%d ", b[i] );
- }*/
- cout<<manacher(j)<<endl;
- }
- return ;
- }
【2018.07.28】(字符串/回文串)学习Manacher算法小记的更多相关文章
- UVA 11584 Partitioning by Palindromes 划分回文串 (Manacher算法)
d[i]表示前面i个字符划分成的最小回文串个数, 转移:当第i字符加进来和前面区间j构成回文串,那么d[i] = d[j]+1. 要判断前面的字符j+1到i是不是回文串,可以用Manacher算法预处 ...
- 回文串的Manacher算法
Manacher算法较传统算法的优化之处在于它对每个回文中心寻找回文半径的时候并不是都从半径为1开始找的,而是利用前面已经完成的任务,寻找一个初始的开始搜索的半径大小,复杂度是线性的. 参考博客:ht ...
- 最长回文串(manacher算法)
; ; int p[N]; char str[LEN], tmp[N]; //p[i]表示以str[i]为中心的回文往右延伸的 最长长度 void manacher(char* str, int* p ...
- 计算字符串的最长回文子串 :Manacher算法介绍
转自: http://www.open-open.com/lib/view/open1419150233417.html Manacher算法 在介绍算法之前,首先介绍一下什么是回文串,所谓回文串,简 ...
- 【BZOJ4755】扭动的回文串(Manacher,哈希)
[BZOJ4755]扭动的回文串(Manacher,哈希) 题面 BZOJ 题解 不要真的以为看见了回文串就是\(PAM,Manacher\)一类就可以过. 这题显然不行啊. 我们主要考虑如何解决跨串 ...
- Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法)
Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...
- 最长回文子串的Manacher算法
对于一个比较长的字符串,O(n^2)的时间复杂度是难以接受的.Can we do better? 先来看看解法2存在的缺陷. 1) 由于回文串长度的奇偶性造成了不同性质的对称轴位置,解法2要对两种情况 ...
- 字符串的最长回文串:Manacher’s Algorithm
题目链接:Longest Palindromic Substring 1. 问题描述 Given a string S, find the longest palindromic substring ...
- 小白月赛13 B小A的回文串 (马拉车算法求最长回文子串)
链接:https://ac.nowcoder.com/acm/contest/549/B来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...
随机推荐
- WebSocket 的应用
后面用到了再来做整理 链接地址:https://www.cnblogs.com/zhaof/p/9833614.html
- H5 - 简学
什么是HTML? HTML 是用来描述网页的一种语言. 0.HTML 指的是超文本标记语言 1.HTML 不是一种编程语言,而是一种标记语言 2.标记语言是一套标记标签 3.HTML 使用标记标签来描 ...
- Chrome安装crx文件的插件时出现“程序包无效”
有趣的事,Python永远不会缺席! 如需转发,请注明出处:小婷儿的python https://www.cnblogs.com/xxtalhr/p/11043453.html 链接:https: ...
- Linux文件(夹)属性
ll 或者 ls -lh 查看文件属性:
- Spring Boot 揭秘与实战之RabbitMQ
Spring Boot 整合 RabbitMQ Spring Boot 整合 RabbitMQ 是非常容易,只需要两个步骤. 首先,在 pom.xml 中增加 RabbitMQ 依赖. <dep ...
- CentOS7安装CDH 第十四章:CDH的优化
相关文章链接 CentOS7安装CDH 第一章:CentOS7系统安装 CentOS7安装CDH 第二章:CentOS7各个软件安装和启动 CentOS7安装CDH 第三章:CDH中的问题和解决方法 ...
- Android和kali的互操作性
1.手机上讲kali Linux系统安装上面实现小巧方便的移动渗透测试工具 其实我们都知道 Android操作系统是基于linux 开发的,这就为我们将kali linux 系统移植到手机上提供了原理 ...
- nginx实现fastcgi反向代理
实现FastCGI: CGI的由来:最早的Web服务器只能简单地响应浏览器发来的HTTP请求,并将存储在服务器上的HTML文件返回给浏览器,也就是静态html文件,但是后期随着网站功能增多网站开发也越 ...
- python中赋值和浅拷贝与深拷贝
初学编程的小伙伴都会对于深浅拷贝的用法有些疑问,今天我们就结合python变量存储的特性从内存的角度来谈一谈赋值和深浅拷贝~~~ 预备知识一——python的变量及其存储 在详细的了解python中赋 ...
- 云计算(5)---MapReduce
什么是MapReduce 例如用MapReduce如何计算12+22+32+42 用MapReduce执行Wordcount 步骤1:Map map task1 和map task2是独立,并行进行 ...