leetcode [005] : Longest Palindromic Substring
2015-09-15 10:59
363 查看
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
思路:
两种做法
第一种做法:动态规划
1、设f[i][j]表示从下标i到j的字符串是不是回文串
2、f[i][j] = (f[i + 1][j - 1] && s[i] == s[j])
3、这个动态规划的阶段划分根本就是减少2的长度后,看能不能继续扩展
4、边界条件:
a.单个字符都是回文的
b.既然要砍掉2的长度才能判断以前的阶段,那么我们可以直接构建2的长度为边界条件(if (s[k] == s[k + 1]) 则是回文的)
5、驱动阶段划分的是字符串的长度
注意:很遗憾的是,上面的算法没有能够通过leetcode,错误原因是内存不够
分析一下,字符串最长如果是1000的话,那么存储空间就是1000 * 1000
为了能让动态规划也能够通过leetcode oj,我把上面的状态转移方程的f[i][j]的意义改为"以i下标开始,j长度的字符串是否为回文"
这样在动态开辟空间的时候,能够节约一半的空间,因为i越靠后,j的值也就越小
源代码如下:
第二种做法:
用Manacher算法,具体的Manacher算法可以去网上搜索,我是看的如下这篇文章
http://www.open-open.com/lib/view/open1419150233417.html
其主要思想是通过回文串的对称性,查看自己的子串是否也是回文串,当不满足条件或者越界的时候,就继续向后遍历
具体的算法,参见网上的各文章,自己演算一遍就很清楚了
我的代码有一些冗余,但在leetcode上也算跑出了4ms的好成绩,差强人意吧
源代码如下:
思路:
两种做法
第一种做法:动态规划
1、设f[i][j]表示从下标i到j的字符串是不是回文串
2、f[i][j] = (f[i + 1][j - 1] && s[i] == s[j])
3、这个动态规划的阶段划分根本就是减少2的长度后,看能不能继续扩展
4、边界条件:
a.单个字符都是回文的
b.既然要砍掉2的长度才能判断以前的阶段,那么我们可以直接构建2的长度为边界条件(if (s[k] == s[k + 1]) 则是回文的)
5、驱动阶段划分的是字符串的长度
注意:很遗憾的是,上面的算法没有能够通过leetcode,错误原因是内存不够
分析一下,字符串最长如果是1000的话,那么存储空间就是1000 * 1000
为了能让动态规划也能够通过leetcode oj,我把上面的状态转移方程的f[i][j]的意义改为"以i下标开始,j长度的字符串是否为回文"
这样在动态开辟空间的时候,能够节约一半的空间,因为i越靠后,j的值也就越小
源代码如下:
#include <iostream> #include <string> #include <vector> using namespace std; class Solution { public: string longestPalindrome(string s) { int iLen = s.size(); if (iLen == 0) return s; bool ** pArr = NULL; pArr = (bool **)new bool *[iLen]; for (int i = 0; i < iLen; ++i) { pArr[i] = new bool[iLen - i + 1]; } int iMaxLen = 0; string strResult; for (int i = 1; i <= iLen; ++i) { for (int j = 0; j <= iLen - i; ++j) { if (i == 1) { pArr[j][1] = true; } else if (i == 2) { if (s[j] == s[j + 1]) { pArr[j][2] = true; } else { pArr[j][2] = false; } } else if (pArr[j + 1][i - 2] && s[j] == s[j + i - 1]) { pArr[j][i] = true; } else { pArr[j][i] = false; } if (pArr[j][i] && i > iMaxLen) { iMaxLen = i; strResult = s.substr(j, i); } } } for (int i = 0; i < iLen; ++i) { delete [] pArr[i]; } delete [] pArr; return strResult; } }; int main() { Solution a; string strResult = a.longestPalindrome("aa"); printf("%s\n", strResult.c_str()); system("pause"); return 0; }
第二种做法:
用Manacher算法,具体的Manacher算法可以去网上搜索,我是看的如下这篇文章
http://www.open-open.com/lib/view/open1419150233417.html
其主要思想是通过回文串的对称性,查看自己的子串是否也是回文串,当不满足条件或者越界的时候,就继续向后遍历
具体的算法,参见网上的各文章,自己演算一遍就很清楚了
我的代码有一些冗余,但在leetcode上也算跑出了4ms的好成绩,差强人意吧
源代码如下:
#include <iostream> #include <string> #include <vector> using namespace std; class Solution { public: string longestPalindrome(string s) { string strConvert; if (s.size() <= 1) return s; for (int i = 0; i < s.size(); ++i) { strConvert += '#'; strConvert += s[i]; } strConvert += '#'; int p0 = 0, p = 0, j; int * pLen = new int[strConvert.size()]; pLen[0] = 1; int iMaxLen = 1; int iMaxLabel = 0; int iCount = 0; for (int i = 1; i < strConvert.size(); ++i) { if (i <= p) { j = 2 * p0 - i; if (pLen[j] + i - 1 < p) { pLen[i] = pLen[j]; } else { iCount = p - i + 1; int k = p + 1; while (k < strConvert.size() && 2 * i - k >= 0 && strConvert[k] == strConvert[2 * i - k]) { ++iCount; ++k; } pLen[i] = iCount; p0 = i; p = i + iCount - 1; } } else { iCount = 1; int k = i + 1; while ( k < strConvert.size() && \ 2 * i - k >= 0 && \ strConvert[k] == strConvert[2 * i - k]) { ++iCount; ++k; } pLen[i] = iCount; p0 = i; p = i + iCount - 1; } if (pLen[i] > iMaxLen) { iMaxLen = pLen[i]; iMaxLabel = i; } } delete [] pLen; string strResult; if (iMaxLabel % 2) { strResult = s.substr(iMaxLabel / 2 - (iMaxLen - 1) / 2, iMaxLen - 1); } else { strResult = s.substr((iMaxLabel - 1) / 2 - (iMaxLen - 1) / 2 + 1, iMaxLen - 1); } return strResult; } }; int main() { Solution a; string strResult = a.longestPalindrome("abba"); printf("%s\n", strResult.c_str()); system("pause"); return 0; }
相关文章推荐
- java--webservices【jdeveloper】
- HDOJ-5446/2015 ACM/ICPC Asia Regional Changchun Online 1010(数论)
- ssh 批量配置互信
- objective-C
- 提升用户体验!29个使用动画效果的网站布局
- linux下为php5.5安装apc失败解决办法
- android.support.v4.view.ViewPager 如何动态更换显示内容
- #include<string> 与#include<string.h>
- android异步任务详解 AsynTask
- 微信JAVA接入公共类
- Mysql:修改root密码
- Android Studio - 详解build.gradle
- 三列布局
- Nginx 相关配置优化
- 05_一对一关联表查询:有二种方式
- 代码设置Android EditText的相关问题。输入长度maxLength
- JS实现base64编码与解码
- 如何通过官方渠道为Windows 10 添加具有中国特色的字体
- 在CentOS5.2+apache2.2下安装配置mod_ssl
- cocos-2dx v3.8 关于未定义标识符visibleSize的问题