【最长回文子串】Manache算法,O(N)时间复杂度
2016-05-06 11:15
441 查看
问题描述:
找一个字符串里的最长回文子串
暴力法:定中心,从0长度向两端扩展的方法O(n^2), n >= 10^5还是超时,故只能《O(n^2)
Manacher's 算法:定中心,从p[r],(已能确定以该点为中心两端是回文的长度开始), 向两端扩展,时间复杂度, O(n)
算法如下:
示意图:
######################
r是当前中心
cen的上一个回文串的中心
######################
定义:
cen:当前匹配的上一个回文串的中心点
p[i]: 以i为中心两端满足回文的长度
r:从0到len-1遍历
l:r关于cen的对称点
绿色:表示已经确定满足回文的部分
目标: 求P数组
步骤:
0. r 遍历 判断是否小于cen+p[cen],是则下一步,否则p[r]=0, (在不在上一个回文串可达的内部,利用的就是已经匹配的回文串左右相等)
1. 确定p[r]已经能确定的大小,(在上一个回文串可达的内部,利用的就是已经匹配的回文串左右相等)
1> 蓝色情况:p[r] = cen+p[cen]-r, 左边的回文长度在边界外,= r 到边界的距离
2> 红色情况:p[r] = p[l],在当前cen+-p[cen]两端边界内
2. 在p[r]的基础上,while(str[r-p[r]]==str[r+p[r]])p[r]++,
This is the key!!!!!!!p[r]不是都从0开始的
如果是普通的方法,
以r为中心,向两端扩展则时间复杂度为O(n^2)
原理实现:
应用:
找一个字符串里的最长回文子串
暴力法:定中心,从0长度向两端扩展的方法O(n^2), n >= 10^5还是超时,故只能《O(n^2)
Manacher's 算法:定中心,从p[r],(已能确定以该点为中心两端是回文的长度开始), 向两端扩展,时间复杂度, O(n)
算法如下:
示意图:
######################
r是当前中心
cen的上一个回文串的中心
######################
定义:
cen:当前匹配的上一个回文串的中心点
p[i]: 以i为中心两端满足回文的长度
r:从0到len-1遍历
l:r关于cen的对称点
绿色:表示已经确定满足回文的部分
目标: 求P数组
步骤:
0. r 遍历 判断是否小于cen+p[cen],是则下一步,否则p[r]=0, (在不在上一个回文串可达的内部,利用的就是已经匹配的回文串左右相等)
1. 确定p[r]已经能确定的大小,(在上一个回文串可达的内部,利用的就是已经匹配的回文串左右相等)
1> 蓝色情况:p[r] = cen+p[cen]-r, 左边的回文长度在边界外,= r 到边界的距离
2> 红色情况:p[r] = p[l],在当前cen+-p[cen]两端边界内
2. 在p[r]的基础上,while(str[r-p[r]]==str[r+p[r]])p[r]++,
This is the key!!!!!!!p[r]不是都从0开始的
如果是普通的方法,
以r为中心,向两端扩展则时间复杂度为O(n^2)
原理实现:
#include<string> #include<iostream> #include<vector> using namespace std; void solve(string s) { int l, r; int len = s.length(); int cen = 0; vector<int> p; p.push_back(0); for (r = 0; 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"); } int main() { solve("11111111111"); return 0; }
应用:
相关文章推荐
- On Error Resume Next 语句
- 简单对比分析Ruby on Rails 和 Laravel
- VBScript中On Error语句用法小结
- 解析sql语句中left_join、inner_join中的on与where的区别
- INSERT INTO .. ON DUPLICATE KEY更新多行记录
- win7安装ruby on rails开发环境
- jQuery on()绑定动态元素出现的问题小结
- jQuery事件绑定.on()简要概述及应用
- jQuery中on()方法用法实例详解
- 浅析jQuery事件之on()方法绑定多个选择器,多个事件
- jQuery绑定事件on()与弹窗的简要概述
- jQuery中delegate与on的用法与区别示例介绍
- mysql ON DUPLICATE KEY UPDATE语句示例
- List all the Databases on a SQL Server
- 用实际代码演示Ruby的容易被误解的6个特性
- 深入Oracle的left join中on和where的区别详解
- jQuery中bind(),live(),delegate(),on()绑定事件方法实例详解
- jQuery中delegate和on的用法与区别详细解析
- Apache No space left on device: mod_rewrite: could not create rewrite_log_lock Configuration Failed