hiho一下 第一周 最长回文子串
描述
小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。
这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”
小Ho奇怪的问道:“什么叫做最长回文子串呢?”
小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~”
小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢?
小Hi笑着说道:“这个很容易啦,你只需要写一个程序,先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”
良久,小Ho仍然没有头绪,于是只能向小Hi求助。 小Hi清了清嗓子,缓缓说道:“让我从简单的说起吧,我给你一个字符串,
你能不能告诉我它是不是一个回文串呢?” 小Ho回答道:“这个我当然可以啦!只要将这个字符串反过来,
然后比较和原来的字符串是不是一样的不就行了?” 小Hi追问道:“也就是说你想要新建一个字符串咯?” 小Ho道:“那是当然,不然怎么比较呢?” 小Hi笑道:“但是你有没有注意到你在比较原来的字符串A和新字符串B
的时候,A的第一个字符就是B的最后一个字符,而A的最后一个字符
就是B的第一个字符,那么这样就比较了两次是不是浪费了效率呢?” 小Ho恍然道:“似乎是这样的!我知道了,我也不需要新建一个字符串
了,我只需要比较A的第一个字符和最后一个字符是否相同,
第二个字符和倒数第二个字符是否相同,以此类推,
这样就只要比较字符串长度的一半次数就行了是不是?” 小Hi回答道:“没错!那你对于一个字符串,一一枚举它的子串,
然后判断这个子串是不是回文子串,如果是的话就更新
当前保存的最长的那一个,是不是就可以了?” 小Ho开心道:“是的!这个问题是不是就这么解决了?” 小Hi叹息道:“NONONO!你这最多也就拿个60分吧。” 小Ho遗憾的说道:“才及格啊,那我要怎么多拿点分呢?”
提示一
小Hi道:“不急不急,待我慢慢道来,你有没有想过之前的解法有没有
什么问题?” 小Ho问道:“有什么问题?” 小Hi道:“你想想,如果一个字符串的[, ]这一段已经不是
回文子串了,[, ]这一段还有可能是回文子串么?” 小Ho惊道:“好像不可能,那我之前不是有很多的计算都白费了,
有没有什么办法来解决这个问题呢?我得好好想想!”
言罢,小Ho沉思了起来。 良久,代表着成功的微笑出现来的小Ho的嘴边:“我知道了!
我在枚举子串的时候换一种方式来进行枚举,不是枚举它的起止位置
而是尝试枚举子串的中心位置,然后再从小到大依次枚举
这个子串的长度,一旦发现已经不是一个回文串了就继续尝试
下一个中心位置,这样,似乎就能够避免掉很多问题呢!” 小Hi赞许的点了点头,说道:“没错,这样的确会在一些情况下降低
用于计算的时间呢,但是一个全是a的字符串,你这样的枚举方法
似乎也没有多大用处呢?不过这样你也能拿个80分了哦!” 小Ho点了点头,说道:“没错,在最坏情况下,这种方法并没有
比之前的方法好到哪里去,但是我的直觉告诉我肯定有更加高效
的方法来进行计算呢,让我再好好想想吧!。”
提示二
小Ho这一想就是三天,小Hi也是看不下去了,决定来开导开导小Ho:“小Ho,你有没有想过,在之前的计算中,计算出以每一个位置为中心的最长回文子串的长度有没有什么用呢?” 小Ho答道:“我想想,如果以第5个字符为中心的最长回文子串的长度是5的话,这就告诉了我[, ]这一段是一个回文子串,所以呢?” 小Hi继续提示道:“假设这时候你想要计算以第6个字符为中心的最长回文子串的长度,你有没有什么已知的信息了?” 小Ho边想边说道:“唔,首先第6个字符和第4个字符是一样的,第7个字符和第3个字符是一样的,而第5个字符本身就肯定和第5个字符一样,那么如果[, ]这一段是回文子串的话,那么[, ]这一段肯定也是回文子串。也就是说,如果令f[i] 表示以第i个字符为中心的最长回文子串的长度,我们就会有f[i] >= f[i–]?” “不对,还要考虑到f[i – ]的值,如果f[i – ]太小就没有意义了,应该是f(i)≥min{f(i-), f(i-)-}。”小Ho接着补充道。 “没错,但是还有一个问题,如果此时我告诉你f() = ,但是f() = , f() = 3呢?”小Hi追问道。 小Ho想了想,回答道:“理论上来说,我可以通过这些信息知道f()>=,但是由于f()=1所以我只能计算出来f()>=-1我知道了,我不应该是通过f(i – )来辅助计算,而是通过使得右边界(j + f(j) / )最大的那个j来辅助计算才是,所以公式将变成 f(i) ≥ min{f(*j-i) , f(j) -*(i-j)}这种形式了!” 小Hi继续问道:“那知道了这个公式之后,你打算怎么做呢?” 小Ho想也没想便道:“这简单,我只要在之前枚举中心位置那种方法的基础上,统计使得回文串右边界(j + f(j) / )最大的那个j,然后再计算每一个i的时候,都可以通过f(i)≥min{f(*j-i), f(j)-*(i-j)}这个公式来知道f(i)的一个最小值,这样即使是在我们所提到的那种最坏情况下,也可以节省掉很多不必要的计算呢~
提示三
一晃就是一周过去了,小Hi还是没有看到小Ho写的程序,于是决定上门去问问。到了小Ho家,小Hi惊讶的发现小Ho对着电脑屏幕,一脸郁闷的样子,于是他走上前问道:“小Ho小Ho,你怎么了啊?” 小Ho一点精神也没有的回答道:“就是上周的那个回文子串的程序啊,我写的时候发现我们当时考虑的解决方法只能处理长度为奇数的回文子串,长度为偶数的回文子串似乎要进行一点点细微的修改,但是这样修改过后就不能用我们最后写出的那个公式来互相帮助进行运算了,要进行很复杂的讨论,我就是一直在想有没有很优美的方法能来解决这个问题。” 小Hi惊讶道:“你就想这个想了一周么?我猜你一定是绕进了分类讨论的这个胡同里走不出来了,为什么不想想有没有别的解决方法呢?” 小Ho问道:“还有什么解决方法呀?” 小Hi答道:“既然长度为偶数的回文子串不好处理,我们为什么不去掉这些回文子串,只处理长度为奇数的回文子串呢?” 小Ho叹息道:“但是长度为偶数的回文子串也可以是答案啊!”
“除非……”小Hi插嘴道。 “除非什么?”小H问道。 “你将所有的长度为偶数的回文子串都变成长度为奇数的回文子串啊,你想想之所以是为偶数,那是因为没有一个中心字符,但是如果我们在原来字符串的基础上,在任意两个相邻的字符间都插入一个特殊字符,是不是无论是原来字符串中长度为奇数的回文子串还是长度为偶数的回文子串,在新的字符串中都有一个长度为奇数的回文子串与之进行对应呢?” “哦!我了解了,这样我只需要对新的字符串按照我们之前的算法进行计算,统计出的最长回文子串将那些特殊字符去掉之后,就是原来字符串里的最长回文子串了。”小Ho开心的笑道,一连几天的郁闷也是一扫而空。 “但是要注意哦,我们希望得到的最长是原来字符串里的最长,而不是新字符串里的最长,毕竟特殊字符的个数会因为中心字符是不是特殊字符而有差别的哦。”小Hi提醒道。 “恩恩,这样我总能拿到满分了吧?” “没错呢!”
提示四
My idea:
对于这道题,比较简单的方法就是对于给定的字符串 我们把每一个字符都当做回文串的中心来计算当前回文串的长度,
从而找到最长的一个对于连续相同的字符子串来说它一定是回文的 ~so 这里可以有一点小小的优化
即把这个子串当做一个字符来处理
#include <stdio.h>
#include <string.h> char str[];
int f(char *str)
{
int i,s,e,m=,n;
for (i = ; str[i]; i ++)
{
s = i; e = i;
while (str[e+] == str[i]) //出现连续相同字符的子串
++ e;
i = e;
while (str[s-] == str[e+]) { // 以当前位置作为回文串的中心
-- s; ++ e;
}
n = e-s+; // up最大的长度
if (n > m) m = n;
}
return m;
}
int main ()
{
int n;
str[] = '#'; // 防止越界
scanf("%d",&n);
while (n --)
{
scanf("%s",str+);
printf("%d\n",f(str));
}
return ;
}
hiho一下 第一周 最长回文子串的更多相关文章
- hiho一下第一周 最长回文子串
题目链接:http://hihocoder.com/contest/hiho1/problem/1 #include <iostream> #include <cstdio> ...
- 【hiho一下】第一周 最长回文子串
题目1:最长回文子串 题目原文:http://hihocoder.com/contest/hiho1/problem/1 [题目解读] 题目与 POJ 3974 palindrome 基本同样.求解最 ...
- hiho 第1周 最长回文子串
题目链接:http://hihocoder.com/problemset/problem/1032 #include <bits/stdc++.h> using namespace std ...
- hihoCoder第一周---最长回文子串(1032)
其实这就是mancher算法的板子题,贴个代码好了. 思想请见我的另一篇博客: https://blog.csdn.net/qq_41090676/article/details/86768361 # ...
- hihoCoder hiho一下 第一周 #1032 : 最长回文子串 (Manacher)
题意:给一个字符串,求最长回文子串的长度. 思路: (1)暴力穷举.O(n^3) -----绝对不行. 穷举所有可能的出现子串O(n^2),再判断是否回文O(n).就是O(n*n*n)了. (2)记录 ...
- hihocoder 第一周 最长回文字串
题目1 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程 ...
- hiho #1032: 最长回文子串
#1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在 ...
- HiHo 1032 最长回文子串 (Manacher算法求解)
/** * 求解最长回文字串,Manacher算法o(n)求解最长回文子串问题 **/ #include<cstdio> #include<cstdlib> #include& ...
- Manacher's algorithm: 最长回文子串算法
Manacher 算法是时间.空间复杂度都为 O(n) 的解决 Longest palindromic substring(最长回文子串)的算法.回文串是中心对称的串,比如 'abcba'.'abcc ...
随机推荐
- [原创]markdown语法学习(commonmark)
CommonMark是markdown的解析器,以下是部分学习链接: commonmark规范 https://spec.commonmark.org/ commonmark帮助 https://co ...
- 进阶篇:3.9)3d打印件设计
本章目的:了解3d打印,购买3d打印机. 1.3d打印基础知识: 现在主流的3d打印技术有4种:①FDM:②SLA:③SLS:④3DP.具体如下: ①熔融沉积造型(Fused deposition m ...
- nginx(四)-负载均衡
负载均衡,我认为是nginx最重要的功能了.那什么是负载均衡呢. 比如有一个服务,它访问量很大,一台机器吃不消了,怎么办,我们准备两台.分一部分的请求出来.现在有两台服务器提供这个服务.我们访问其中一 ...
- Java 继承学习
Java 继承 继承实现: 在Java中,如果实现继承的,需要使用Java关键字——extends : 被继承的类叫做超类,继承超类的类叫子类.(一个子类亦可以是另一个类的超类) class 子类 e ...
- ionic3 引入第三方库(jquery)
安装 npm install jquery npm install @types/jquery 在需要的ts文件中引入,一定要在最顶端 import * as $ from '../../../nod ...
- pxe-kickstart
PXE client--->DHCP(pxelinux.0; next-server tftp-server) syslinux vmlinuz initrd.img ks.cfg--- ...
- (转)Mysql数据库管理 表的维护
原文:http://t.dbdao.com/archives/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AE%A1%E7%90%86-%E8%A1%A8%E7%9A%84 ...
- WCF系列教程之初识WCF
本随笔参考自WCF编程系列(一)初识WCF,纯属读书笔记,加深记忆. 1.简介:Windows Communication Foundation(WCF)是微软为构建面向服务的应用程序所提供的统一编程 ...
- Java ArrayList trimToSize()
前几天看了Java ArrayList,没有明白trimToSize()这个方法是什么意思,所以看了一下源码并且debug一下自己的一个例子,明白了其中的含义.贴在这里. ArrayList al = ...
- MySQL通过SQL语句来直接生成新表
1. 既复制表结构,也复制表数据 mysql> CREATE TABLE tmp_table SELECT * FROM dede_news; 说明:这种方法的缺点就是新表中没有了旧表的prim ...