回文串

最长回文子串_Manacher算法_hihoCoder1032

只愿长相守 提交于 2019-12-04 20:11:02
题目: http://hihocoder.com/problemset/problem/1032 时间限制: 1000ms 单点时限: 1000ms 内存限制: 64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。 这一天,他们遇到了一连串的字符串,于是小 Hi 就向小 Ho 提出了那个经典的问题:“小 Ho ,你能不能分别 在这些字符串中找到它们每一个的最长回文子串 呢?” 小Ho奇怪的问道:“什么叫做最长回文子串呢?” 小Hi回答道: “一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~” 小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢? 小Hi笑着说道:“这个很容易啦,你只需要写一个程序, 先从标准输入读取一个整数N (N<=30) ,代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。 而你要告诉我你的答案的话, 只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了! 你看这就是一个例子。” 样例输入 3 abababa aaaabaa acacdas

算法题:最长回文子串

感情迁移 提交于 2019-12-04 11:53:45
一、问题描述: 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2: 输入: "cbbd" 输出: "bb" 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-palindromic-substring 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 二、我的解法: 我的思路: 先假定回文子串长度为1,然后逐步增加长度,当发现以i为中心的回文子串达到当前长度时,继续增加长度,如果出现连续两个长度都能没达到时,不再增加,因为不可能出现更大长度的子串了。 java代码: class Solution { public String longestPalindrome(String s) { if(1 >= s.length()) return s; int longest = 1; String longestPalindrome = s.substring(0,1); String longestPalindromeTmp = s.substring(0,1); int longestTmp = 1; int fir = 0; for(int i=0;

最长回文子串 —— Manacher (马拉车) 算法

半城伤御伤魂 提交于 2019-12-04 09:36:25
最长回文子串 回文串 就是原串和反转字符串相同的字符串。比如 aba , acca 。前一个是奇数长度的回文串,后一个是偶数长度的回文串。 最长回文子串 就是一个字符串的所有子串中,是回文串且长度最长的子串。 Brute Force 做法 枚举所有子串,判断是否是回文串,然后寻找最大长度。寻找所有子串要两重循环,判断是否是回文要一重循环,总体时间复杂度 \(O(n^3)\) 。 稍微优化一下,可以枚举对称中心,然后向两边扩展,直到遇到两个不同的字符,枚举下一个对称中心,寻找其中的最大长度,时间复杂度 \(O(n^2)\) 。 还可以使用 DP 解决,求原串与反转字符串的最长公共子序列 (LCS),时间复杂度 \(O(n^2)\) 。 Manacher 算法 接下来就是重点了,Manacher 算法,在1975年由一个叫 Manacher 的人发明的。能够在 \(O(n)\) 的时间求得最长回文子串。 前面提到,回文串有奇数长度的和偶数长度的,分类讨论有些复杂,可以参考 这里 。为了避免分类讨论,可以使用一个技巧:在字符串首尾以及每两个字符之间插入一个 '#' 。比如 abaacca ,转换后就是 #a#b#a#a#c#c#a# 。那么不管是奇回文 aba 还是偶回文 acca ,转换后都是奇回文 ( #a#b#a# 和 #a#c#c#a# )。 string init(string

最长回文子串――Manacher算法

匿名 (未验证) 提交于 2019-12-02 23:57:01
Manacher算法,又叫“马拉车”算法,可以在时间复杂度为O(n)的情况下求解一个字符串的最长回文子串长度的问题。 一、回文子串的一般解法 比较简单的思路是将字符串的每一个字符作为回文子串的中心对称点,每次保存前面求得的回文子串的最大值,最后得到的就是最长的回文子串的长度,这种方式的时间复杂度是O(n^2)。在求解过程中,基数的回文子串与偶数的回文子串是不一样的。比如最长回文子串为aba,对称中心就是b,如果最长回文子串为abba,则对称中心应该为两个b之间,为了解决这个问题,可以在每个字符两边加上一个符号,具体什么符号(是字符串里面的符号也行)对结果没有影响,比如加上“#”,则上述的两个序列变成了#a#b#a#和#a#b#b#a#,求出的长度分别为6和9,再除以2就可以得到最后的结果3和4。这种方式的时间复杂度太高,下面介绍时间复杂度为O(n)的Manacher算法。 二、Manacher算法中的基础概念 1、回文半径数组radius 回文半径数组radius是用来记录以每个位置的字符为回文中心求出的回文半径长度,如下图所示,对于p1所指的位置radius[6]的回文半径是5,每个位置的回文半径组成的数组就是回文数组,所以#a#c#b#b#c#b#d#s#的回文半径数组为[1, 2, 1, 2, 1, 2, 5, 2, 1, 4, 1, 2, 1, 2, 1, 2, 1]。 2

5. 最长回文子串

匿名 (未验证) 提交于 2019-12-02 23:43:01
s s 1000 1 : "babad" : "bab" : "aba" 2 : "cbbd" : "bb" 解法 1:中心扩散 思路很简单:遍历每一个索引,以这个索引为中心,往两边扩散,看最多能扩散多远。具体的做法是利用“回文串”中心对称的特点,在枚举子串的过程中进行剪枝。要注意一个细节:回文串的长度可能是奇数,也可能是偶数。 我们完全可以设计一个方法,兼容以上两种情况: 1、如果传入重合的索引编码,进行中心扩散,此时得到的最长回文子串的长度是奇数; 2、如果传入相邻的索引编码,进行中心扩散,此时得到的最长回文子串的长度是偶数。 Python: class Solution: def longestPalindrome(self, s): size = len(s) if size == 0: return '' # 至少就是 1 longest_palindrome = 1 longest_palindrome_str = s[0] for i in range(size): # 返回当前最长回文子串、和这个最长回文子串的长度 palindrome_odd, odd_len = self.__center_spread(s, size, i, i) palindrome_even, even_len = self.__center_spread(s, size, i, i +

leetcode 5 最长回文子串

二次信任 提交于 2019-12-02 06:53:24
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2: 输入: "cbbd" 输出: "bb" 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-palindromic-substring 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。    解法1:最长公共子串 容易想到,回文意味着将这个字串反转,回文的部分一定是公共子串。 子串是一种动态规划的思路。这里借用别人的说明,很详细: 但是这里依然有着一些区别:如果存在abcde...edcba的字串,那么abcde会被认为回文。所以我们需要二次检测来筛除这种问题。 int res[1005][1005];//这个涉及栈的大小问题,本机上开在函数内会超界。 class Solution { public: string longestPalindrome(string s) { string sraw=s; reverse(s.begin(),s.end());//反转字串 int len=s.length(); int maxlen=0;//最大长度 string ans;//最大回文子串 for

acwing 139. 回文子串的最大长度

情到浓时终转凉″ 提交于 2019-12-01 02:42:39
题面: 如果一个字符串正着读和倒着读是一样的,则称它是回文的。 给定一个长度为N的字符串S,求他的最长回文子串的长度是多少。 输入格式 输入将包含最多30个测试用例,每个测试用例占一行,以最多1000000个小写字符的形式给出。 输入以一个以字符串“END”(不包括引号)开头的行表示输入终止。 输出格式 对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。 每个输出占一行。 输入样例: abcbabcbabcba abacacbaaaab END 输出样例: Case 1: 13 Case 2: 6题解:马拉车的模板题,这题用字符哈希偏复杂: Manacher算法,但是我们这道题目是锻炼我们的哈希水平,所以我们这里只说如何用哈希算法求解.作者忘记如何使用马拉车算法了… 上一道兔子兔子兔子的题目,我们知道判断两个字符串是否相等,可以使用字符串哈希,也就是将字符串算成P进制数值,然后区间和判断即可,那么这道题目我们需要一个正的字符串,还需要一个反的字符串,然后如果正字符串等于反的字符串,那么奇数回文串就2+1,偶数回文串就直接2即可.之所以要这么做,因为我们是要回文对不对,我们需要将回文拆解成为一个正字符串和一个反字符串,这样才好处理这道题目. 既然如此,我们可以算出一个前缀和,再算出一个后缀和,然后就可以知道,正字符串和一个反字符串

Leetcode(5)最长回文子串

白昼怎懂夜的黑 提交于 2019-11-30 23:54:02
Leetcode(4)寻找两个有序数组的中位数 [题目表述]: 给定一个字符串 s,找到 s 中 最长 的回文子串。你可以假设 s 的最大长度为 1000。‘ 第一种方法:未完成;利用回文子串的特点 一开始我的思路如下:回文子串的特点是首尾字母相同,所以我对每一个字母都找到位于它后面的相同字母,利用切片判断这一段是否为回文子串(str[i:j]==str[i:j][::-1]).时间复杂度很高,主要是因为str.find操作非常耗时. class Solution(object): def longestPalindrome(self, s): """ :type s: str :rtype: str """ res="" res+=s[0] res_star=0 res_end=0 Maxsize=1 for i in range(len(s)): nPos=i i_number=s[i:].count(s[i]) if i_number==1: continue while i_number!=1: if s[i+1]==s[i]: i_number=i_number-1 nPos=i+1 if Maxsize!=max(Maxsize,len(s[i:nPos+1])): Maxsize=len(s[i:nPos+1]) res_star,res_end=i,nPos+1

最长回文子串——Manacher算法

喜你入骨 提交于 2019-11-29 02:43:58
Manacher算法,又叫“马拉车”算法,可以在时间复杂度为O(n)的情况下求解一个字符串的最长回文子串长度的问题。 一、回文子串的一般解法 比较简单的思路是将字符串的每一个字符作为回文子串的中心对称点,每次保存前面求得的回文子串的最大值,最后得到的就是最长的回文子串的长度,这种方式的时间复杂度是O(n^2)。在求解过程中,基数的回文子串与偶数的回文子串是不一样的。比如最长回文子串为aba,对称中心就是b,如果最长回文子串为abba,则对称中心应该为两个b之间,为了解决这个问题,可以在每个字符两边加上一个符号,具体什么符号(是字符串里面的符号也行)对结果没有影响,比如加上“#”,则上述的两个序列变成了#a#b#a#和#a#b#b#a#,求出的长度分别为6和9,再除以2就可以得到最后的结果3和4。这种方式的时间复杂度太高,下面介绍时间复杂度为O(n)的Manacher算法。 二、Manacher算法中的基础概念 1、回文半径数组radius 回文半径数组radius是用来记录以每个位置的字符为回文中心求出的回文半径长度,如下图所示,对于p1所指的位置radius[6]的回文半径是5,每个位置的回文半径组成的数组就是回文数组,所以#a#c#b#b#c#b#d#s#的回文半径数组为[1, 2, 1, 2, 1, 2, 5, 2, 1, 4, 1, 2, 1, 2, 1, 2, 1]。 2

找出字符串中的最长回文子串 - 马拉车算法

耗尽温柔 提交于 2019-11-28 22:36:12
问题: 找出字符串中的最长回文子串 思路: 举例分析下,例如 ”abadaba“ 这个字符串的计算 1、从左往右遍历,整个字符串,把每个字符和字符间的空隙当作回文的中心,然后向两边扩展来找到最长回文串,这种情况下默认得对每一个字符进行计算,计算量比较大,而且有部分计算其实能通过之前的计算得到答案,后面第2点开始讨论下如何减少计算次数 2、利用回文的特性,结合已经计算的部分,尽量减少后面的计算次数。比如下图,当我们计算到第5位的时候,通过前面的计算可以知道2-4位是一个回文子串,由于5也是回文子串,且跨幅度是2-8,因为4位不是回文子串,所以与4对应的6位也不是回文子串,同理可以推断出6-8是一个回文子串 3、由于之前的计算已经知道了第 5位为中心的 abadaba是回文,而第 4位为中心的 a的回文长度是 1,所以第 6位为中心的回文长度只能是 1,不用再去计算了。 4、以第 7位为中心的回文串的计算,由之前分析已经知道最小长度是 3了,但是还是需要进行扩展,因为第 9位是什么根据之前的信息无法得知,需要扩展进行探索。 5、考虑到回文子串可能是复数,这里得在字符之间加多个标记进行特殊处理 总结下步骤: 1、先对字符串进行预处理,两个字符之间加上特殊符号 # 2、然后遍历整个字符串,用一个数组来记录以该字符为中心的回文长度,为了方便计算右边界,在数组中记录长度的一半(覆盖半径) 3