回文串

hihocoder #1032 : 最长回文子串 Manacher算法

坚强是说给别人听的谎言 提交于 2020-04-05 21:00:22
题目链接: https://hihocoder.com/problemset/problem/1032?sid=868170 最长回文子串 时间限制:1000ms内存限制:64MB #### 问题描述 > 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。 > > 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?” > > 小Ho奇怪的问道:“什么叫做最长回文子串呢?” > > 小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~” > > 小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢? > > 小Hi笑着说道:“这个很容易啦,你只需要写一个程序,先从标准输入读取一个整数N(Nsample input 3 abababa aaaabaa acacdas sample output 7 5 3 题解 Manacher算法求解最长回文子串 最后答案为max(P[i]-1) 代码 #include<map> #include<set>

字符串的最长回文子串

▼魔方 西西 提交于 2020-03-28 18:54:45
马拉车(Manacher)算法是在O(n)时间内解决寻找源字符串的最长回文子串S的问题的算法。 朴素算法情况下对于每一个S[i]都要左右遍历其最大回文子串,所以时间复杂度是O(n2) 算法流程分析 由于回文分为偶回文(比如 abab 长度为4)和奇回文(比如 abcba 长度为5),而在处理奇偶问题比较麻烦,所以这里需要做 个预处理,在字符间插入一个特殊字符(这个字符不能在串里出现),将原串转换统一成奇串。 比如原字符串: s =”abbaTNTabcba”   插入字符之后:sNew= “$#a#b#b#a#T#N#T#a#b#c#b#a#”(开头的$是为了防止越界,在下面的代码注释中有体现) 原串s中含有一个偶回文abba和两个奇回文baTNTab、abcba,插入'#'字符后长度都转换成了奇数,比如:#a#b#b#a#长度为 9、#b#a#T#N#T#a#b#长度为15。   算法需要一个与新串sNew等长的辅助数组vector<int> p(sNew.size(),0),其中p[i]表示以sNew[i]为中心的最长回文子串的半径, 若p[i]=1,则该回文子串就是sNew[i]本身。下面我们将新串sNew的最大回文子串半径列出: 例如:以sNew[20]=’c’为中心的最长回文子串半径为6。   由于第一个和最后一个字符都是#号,且也需要搜索回文,为了防止越界

最长回文子串问题 O(n)算法 manacher URAL1297 HDU3068

不问归期 提交于 2020-03-26 01:44:39
先来看一道简单的题, ural1297 给定一个1000长度的字符串,求最长回文子串。 看起来很Naive,乱搞一下,O(n^2)都可以解决。 再来看这个题 HDU3068 120个110000长度的字符串,是不是感觉有点困难了?据说后缀数组也要TLE 给出一个O(n)的解决方案 manacher算法 很有趣的利用了回文子串的性质,进行递推更新。 转载自 http://blog.csdn.net/ggggiqnypgjg/article/details/6645824 这里,我介绍一下O(n)回文串处理的一种方法。Manacher算法. 原文地址: http://zhuhongcheng.wordpress.com/2009/08/02/a-simple-linear-time-algorithm-for-finding-longest-palindrome-sub-string/ 其实原文说得是比较清楚的,只是英文的,我这里写一份中文的吧。 首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长。这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文有多长, 这个算法有一个很巧妙的地方,它把奇数的回文串和偶数的回文串统一起来考虑了。这一点一直是在做回文串问题中时比较烦的地方

最长回文子串 南邮NOJ 1100

你。 提交于 2020-03-23 07:18:26
最长回文子串 时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte 总提交 : 689 测试通过 : 229 题目描述 输入一个字符串,求出其中最大的回文子串。子串的含义是:在原串中连续出现的字符串片段。回文的含义是:正着看和倒着看相同,如abba和yyxyy。在判断时,应该忽略所有标点符号和空格,且忽略大小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符)。 输入 输入字符串长度不超过5000,且占据单独的一行。 输出 输出最长的回文串,如果有多个,输出起始位置最靠左的。 样例输入 Confuciuss say: Madam,I?m Adam. 样例输出 Madam, I?m Adam <span style="font-size:12px;">/* 枚举回文串中的"中间"位置,然后不断向外扩展,直到有字符不同。 */ #include<stdio.h> #include<string.h> #include<ctype.h> #define MAXN 5000+10 char buf[MAXN],s[MAXN]; int p[MAXN]; int main() { int n,m=0,max=0,x,y; int i,j; fgets(buf,sizeof(s),stdin); n=strlen(buf); for

最长回文子串 南邮NOJ 1100

允我心安 提交于 2020-03-16 17:28:01
最长回文子串 时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte 总提交 : 689 测试通过 : 229 题目描述 输入一个字符串,求出其中最大的回文子串。子串的含义是:在原串中连续出现的字符串片段。回文的含义是:正着看和倒着看相同,如abba和yyxyy。在判断时,应该忽略所有标点符号和空格,且忽略大小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符)。 输入 输入字符串长度不超过5000,且占据单独的一行。 输出 输出最长的回文串,如果有多个,输出起始位置最靠左的。 样例输入 Confuciuss say: Madam,I?m Adam. 样例输出 Madam, I?m Adam <span style="font-size:12px;">/* 枚举回文串中的"中间"位置,然后不断向外扩展,直到有字符不同。 */ #include<stdio.h> #include<string.h> #include<ctype.h> #define MAXN 5000+10 char buf[MAXN],s[MAXN]; int p[MAXN]; int main() { int n,m=0,max=0,x,y; int i,j; fgets(buf,sizeof(s),stdin); n=strlen(buf); for

代码题(17)— 最长回文子串、最长回文子序列、回文子串、分割回文串(2)

 ̄綄美尐妖づ 提交于 2020-03-16 08:01:20
1、5. 最长回文子串 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。 示例 1: 输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案。 示例 2: 输入: "cbbd" 输出: "bb"(1)动态规划方法   回文字符串的子串也是回文,P[i][j](表示以i开始以j结束的子串)是回文字符串,那么P[i+1][j-1]也是回文字符串。该问题可以分解成一系列子问题。   定义状态方程和转移方程:   P[i][j]=0表示子串[i,j]不是回文串 P[i][j]=1表示子串[i,j]是回文串   dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true); class Solution { public: string longestPalindrome(string s) { int len = s.size(); if(len < 2) return s; vector<vector<bool>> dp(len, vector<bool>(len, false)); int start = 0, maxlen = 1; dp[0][0] = true; for (int i = 1; i < len; i++) { dp[i][i] = true; dp[i][i-1]

O(n) 求 最长回文子串

假装没事ソ 提交于 2020-02-29 04:48:44
转自: http://bbs.dlut.edu.cn/bbstcon.php?board=Competition&gid=23474 其实原文说得是比较清楚的,只是英文的,我这里写一份中文的吧。 首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长。这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文有多长, 这个算法有一个很巧妙的地方,它把奇数的回文串和偶数的回文串统一起来考虑了。这一点一直是在做回文串问题中时比较烦的地方。这个算法还有一个很好的地方就是充分利用了字符匹配的特殊性,避免了大量不必要的重复匹配。 算法大致过程是这样。先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过。一般可以用‘#’分隔。这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了(见下面的一个例子,回文串长度全为奇数了),然后用一个辅助数组P记录以每个字符为中心的最长回文串的信息。P[id]记录的是以字符str[id]为中心的最长回文串,当以str[id]为第一个字符,这个最长回文串向右延伸了P[id]个字符。 原串: w aa bwsw f d 新串: # w # a # a # b # w # s # w # f # d # 辅助数组P: 1 2 1 2 3 2 1 2 1 2 1 4 1 2 1

5.最长的回文子串

懵懂的女人 提交于 2020-02-16 19:12:02
暴力解法 思路 1、做一个子函数,用于检测输入的字符串是否是回文串 2、使用双指针,头指针从字符串开始处遍历,尾指针每次均从结尾处开始,检查头尾指针之间的字符串是否是回文串,若是,且长度大于之前的长度,则更新,否则进行下次检查,注意,大循环的结束条件可以随着找到回文子串的长度而更新。 代码 # include <stdio.h> # include <string.h> # include <stdlib.h> // for malloc(), free() # define YES 1 # define NO 0 int IsPalindrome ( char * strIn , int strLength ) { for ( int i = 0 ; i < strLength / 2 ; i ++ ) { if ( strIn [ i ] != strIn [ strLength - 1 - i ] ) { return NO ; } } return YES ; } char * longestPalindrome ( char * s ) { int strLength = strlen ( s ) ; if ( strLength < 2 ) { return s ; } char tmpLongestPald [ 1001 ] = { 0 } ;

Leet Code 5.最长回文子串

倾然丶 夕夏残阳落幕 提交于 2020-02-11 17:37:13
给定一个字符串s,找到s中最长的回文子串。你可以假设s的最大长度为1000. 这题是很经典的题目,找到最长回文子串,回文就是bab,cabac这样的。 题解 解法一 暴力法,列举所有的子串,判断是否为回文串,很明显时间复杂度为O(n^2)。 解法二 将原字符串s倒置s',然后寻找最长回文串就变成寻找字符串s和s'的最长公共子串,需要注意的一点,找到最长公共子串后,还需要判断子串是否是回文。 解法三,动态规划 很多时候关于字符串的判断,需要用到动态规划的思想。 我们判断i到j的子串为回文串时,等价于i+1到j-1时回文串&&Si=Sj。时间复杂度仍为O(n^2),空间复杂度也是。 代码 public String longestPalindrome(String s) { int length = s.length(); boolean[][] P = new boolean[length][length]; int maxLen = 0; String maxPal = ""; for (int len = 1; len <= length; len++) //遍历所有的长度 for (int start = 0; start < length; start++) { int end = start + len - 1; if (end >= length) //下标已经越界

[LeetCode]647. 回文子串(DP)

谁说胖子不能爱 提交于 2020-02-11 14:53:40
题目 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。 示例 1: 输入: "abc" 输出: 3 解释: 三个回文子串: "a", "b", "c". 示例 2: 输入: "aaa" 输出: 6 说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa". 注意: 输入的字符串长度不会超过1000。 来源:力扣(LeetCode) 链接: https://leetcode-cn.com/problems/palindromic-substrings 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 题解 状态: boolean dp[i][j]表示s[i to j] 是否是回文串。 状态转移方程: dp[i][j]=dp[i+1][j-1],s.charAt[i]==s.charAt[j] dp[i][j]=true,s.charAt[i]==s.charAt[j] && j<=i+2 dp[i][j]=false,s.charAt[i]!=s.charAt[j] 关键,由于dp[i][j]的计算依赖dp[i+1][j-1],所以外层i遍历为从后向前,内层j遍历为从i向后。 代码 class Solution { public int