【LeetCode 214】最长回文子串
2016-05-06 13:07
573 查看
题目链接:
https://leetcode.com/problems/shortest-palindrome/
题目描述:
给一个字符串s, 求在其前方添加最少的字符使添加后的s是回文串,并返回该回文串。
例如:
输入:1221abc
输出:cba1221abc
输入:121abc
输出:cba121abc
思路:
其实就是求从第一个字母开始,满足最长的回文串。
s = 最长从第一个字母开始的回文串 + 尾巴
ans = 尾巴的逆序 + s
所以,问题转化为求s的最长子回文串
最长回文字串:
暴力法:
定中心,从中心+-0开始 到两端扩展,判断是否回文串,O(n^2),超时
Manacher算法:
从左到右边定中心,从中心+-p[中心]开始向两端扩展, 时间复杂度O(n), 详见前一篇博客 【最长回文子串】Manache算法
回文串两种形式,统一为一种形式
因为回文串有两种形式,
121,奇数
1221,偶数
通过加入符号可以都转换为奇数的情况
121 -> #1#2#1
1221 -> #1#2#2#1#
用转换后的字符换进行处理,求完后再求出,在原字符串的起点,长度即可
实现:
https://leetcode.com/problems/shortest-palindrome/
题目描述:
给一个字符串s, 求在其前方添加最少的字符使添加后的s是回文串,并返回该回文串。
例如:
输入:1221abc
输出:cba1221abc
输入:121abc
输出:cba121abc
思路:
其实就是求从第一个字母开始,满足最长的回文串。
s = 最长从第一个字母开始的回文串 + 尾巴
ans = 尾巴的逆序 + s
所以,问题转化为求s的最长子回文串
最长回文字串:
暴力法:
定中心,从中心+-0开始 到两端扩展,判断是否回文串,O(n^2),超时
Manacher算法:
从左到右边定中心,从中心+-p[中心]开始向两端扩展, 时间复杂度O(n), 详见前一篇博客 【最长回文子串】Manache算法
回文串两种形式,统一为一种形式
因为回文串有两种形式,
121,奇数
1221,偶数
通过加入符号可以都转换为奇数的情况
121 -> #1#2#1
1221 -> #1#2#2#1#
用转换后的字符换进行处理,求完后再求出,在原字符串的起点,长度即可
实现:
#include<string> #include<iostream> #include<vector> using namespace std; class Solution { public: string shortestPalindrome(string s) { int i, j; string s2 = "#"; for (i = 0; i < s.length(); i++) { s2 += s.at(i); s2 += "#"; } vector<int> p = manacher(s2); int cen = 0; for (i = 0; i < p.size(); i++) { if(i - p[i] == 0) { cen = i; } } int maxL = p[cen]; string head = ""; for (j = s.length() - 1; j >= maxL; j--) { head += s.at(j); } s = head + s; return s; } vector<int> manacher(string s) { int l, r; int len = s.length(); int cen = 0; vector<int> p; p.push_back(0); for (r = 1; r < len; r++) { // printf("cen = %d, pcen = %d, r = %d\n", cen, p[cen], r); p.push_back(0); int cenR = cen + p[cen]; if (r <= cenR) { l = 2 * cen - r; p[r] = p[l] < cenR - r ? p[l] : cenR - r; } else { p[r] = 0; } // 这里是关键,如果从r为中心长度为0开始向两边扩展,则复杂度为O(n^2), 这里从p[r]开始扩展 while((r-p[r]-1>=0) && (r+p[r]+1<len) && (s.at(r - p[r] -1) == s.at(r + p[r] + 1))) p[r]++; if (r + p[r] > cenR) { cen = r; } } //cout << s << endl; //int i; //for (i = 0; i < len; i++) { // printf("%d ", p[i]); //} printf("\n"); return p; } }; int main() { Solution s; string ans = s.shortestPalindrome("77777777777777777777777777777777777777771"); cout << ans << endl; return 0; }
相关文章推荐
- 【HUSTOJ】1073: 拐角VI
- iOS开发系列--打造自己的“美图秀秀”
- 关于c#数据库的简单应用-datagriview连接数据库及更相关操作
- Fresco简单的使用—SimpleDraweeView
- Android IOC 框架ViewInject(上)
- 毛玻璃效果
- Android异常捕获02
- Spark流处理解读(3)JOB源码解读
- 类的成员函数做回调函数
- EditTextView的介绍和使用
- Oracle中查询各种对象的方法小结
- 第1章 UML基础:类的关系
- 第十周-点类族设计项目1
- 我经历的IT公司面试及离职感受
- Yii2.0 rules验证规则大全
- web.xml 配置
- ExtJS自定义控件 之一:datetimefield控件
- 上传文件功能-1
- 二叉树的非递归遍历
- NYOJ 题目77 开灯问题