Manacher(马拉车)是一种求最长回文串的线性算法,复杂度O(n)。网上对其介绍的资料已经挺多了的,请善用搜索引擎。

而扩展KMP说白了就是是求模式串和主串的每一个后缀的最长公共前缀【KMP更像是一个自动机】


题目:

POJ 1159: Palindrome

求原字符串最少增加几个字符后可变成回文串,相当于求最长回文子序列的长度。

解法:直接求串S和反转串Sr的最长公共子序列。

#include <cstdlib>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue> #define rep(i, l, r) for(int i = l; i <= r; i++)
#define down(i, l, r) for(int i = l; i >= r; i--)
#define ll long long
#define maxn 10009
#define MAX 1<<30
#define Q 1000000007 using namespace std; int n, dp[][];
char s[]; int main()
{
scanf("%d%s", &n, s);
rep(i, , n) rep(j, , n)
{
dp[i%][j] = max(dp[(i-)%][j], dp[i%][j-]);
if (s[i-]==s[n-j] && dp[(i-)%][j-]+>dp[i%][j]) dp[i%][j] = dp[(i-)%][j-]+;
}
printf("%d\n", n-dp[n%][n]);
return ;
}

HDU 3068: 最长回文

模板题。

#include <cstdlib>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue> #define rep(i, l, r) for(int i = l; i <= r; i++)
#define down(i, l, r) for(int i = l; i >= r; i--)
#define ll long long
#define maxn 234567
#define MAX 1<<30
#define Q 1000000007 using namespace std; int n, l, k[maxn], o, p, ans;
char c[maxn], s[maxn]; int main()
{
while (scanf("%s", c) == )
{
l = strlen(c);
rep(i, , l-) s[i*+] = '$', s[i*+] = c[i];
l = l*+; s[l]=s[l+] = '$'; s[] = '#';
o=p=ans=;
rep(i, , l)
{
k[i] = i<p ? min(k[*o-i], p-i) : ;
while (s[i+k[i]] == s[i-k[i]]) k[i]++;
if (i+k[i]>p) p = i+k[i], o = i;
ans = max(ans, k[i]-);
}
printf("%d\n", ans);
}
return ;
}

POJ 3974: Palindrome

同模板题。

#include <cstdlib>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue> #define rep(i, l, r) for(int i = l; i <= r; i++)
#define down(i, l, r) for(int i = l; i >= r; i--)
#define ll long long
#define maxn 2000009
#define MAX 1<<30
#define Q 1000000007 using namespace std; int t, n, l, k[maxn], o, p, ans;
char c[maxn], s[maxn]; int main()
{
while (++t)
{
scanf("%s", c);
if (c[]=='E') break; l = strlen(c);
rep(i, , l-) s[i*+]='$', s[i*+]=c[i];
l=l*+; s[]='#'; s[l]=s[l+]='$';
ans=o=p=;
rep(i, , l)
{
k[i] = i<p ? min(p-i, k[o*-i]) : ;
while (s[i+k[i]] == s[i-k[i]]) k[i]++;
if (i+k[i]>p) p=i+k[i], o=i;
ans = max(ans, k[i]-);
}
printf("Case %d: %d\n", t, ans);
}
return ;
}

BZOJ 2342: 双倍回文

求最长双倍回文。

我实在是太弱了,于是写了个暴力+最优性剪枝,成功地用O(n^2)的算法AC!【其实正解是要O(nlogn)的算法的】

#include <cstdlib>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue> #define rep(i, l, r) for(int i = l; i <= r; i++)
#define down(i, l, r) for(int i = l; i >= r; i--)
#define ll long long
#define maxn 1000009
#define MAX 1<<30
#define Q 1000000007 using namespace std; int t, n, l, k[maxn], o, p, ans, b[maxn];
char c[maxn], s[maxn]; int main()
{
scanf("%d%s", &l, c);
rep(i, , l-) s[i*+]='$', s[i*+]=c[i];
s[]='#'; s[l*+]='$';
ans=o=p=;
rep(i, , l*+)
{
k[i] = i<p ? min(p-i, k[o*-i]) : ;
while (s[i+k[i]] == s[i-k[i]]) k[i]++;
if (i+k[i]>p) p=i+k[i], o=i;
}
rep(i, , l) b[i+]=k[i*-]/;
rep(i, , l)
down(j, b[i]/, ans+) if (b[i-j]>=j && b[i+j]>=j) ans = j;
printf("%d\n", ans*);
return ;
}

BZOJ 2565: 最长双回文串

求最长双回文串。

对于每个字符,利用单调性质求出往左往右所能找到的最长的回文串。

#include <cstdlib>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue> #define rep(i, l, r) for(int i = l; i <= r; i++)
#define down(i, l, r) for(int i = l; i >= r; i--)
#define ll long long
#define maxn 200009
#define MAX 1<<30
#define Q 1000000007 using namespace std; int t, n, l, k[maxn], o, p, ans, lt[maxn], rt[maxn];
char c[maxn], s[maxn]; int main()
{
scanf("%s", c); l=strlen(c);
rep(i, , l-) s[i*+]='$', s[i*+]=c[i];
s[]='#'; s[*l+]='$';
o = p = ;
rep(i, , l*+)
{
k[i] = i<p ? min(p-i, k[*o-i]) : ;
while (s[i+k[i]] == s[i-k[i]]) k[i]++;
if (i+k[i]>p) p = i+k[i], o = i;
}
o = ; rep(i, , l*+)
{
while (o+k[o]<=i) o++;
lt[i] = i-o;
}
o = l*+; down(i, l*, )
{
while (i<=o-k[o]) o--;
rt[i] = o-i;
}
rep(i, , l*+) if (s[i]=='$' && lt[i] && rt[i] && ans < lt[i]+rt[i]) ans = lt[i]+rt[i];
printf("%d\n", ans);
return ;
}

HDU 3613: Best Reward

这题貌似EXKMP和Manacher都可以做。

#include <cstdlib>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue> #define rep(i, l, r) for(int i = l; i <= r; i++)
#define down(i, l, r) for(int i = l; i >= r; i--)
#define ll long long
#define maxn 500009
#define MAX 1<<30
#define Q 1000000007 using namespace std; int tt, l, n[maxn], ex[maxn], v[maxn], t[];
char c[maxn], s[maxn]; int main()
{
scanf("%d", &tt);
while (tt--)
{
rep(i, , ) scanf("%d", &t[i]);
scanf("%s", s); int l = strlen(s);
rep(i, , l-) c[i] = s[l-i-];
int k, p, a; rep(i, , l-) v[i] = ; rep(i, , l-) ex[i] = n[i] = ;
n[] = ; while (c[n[]] == c[n[]+]) n[]++;
n[] = l; k = ; p = n[];
rep(i, , l-)
{
n[i] = i<p ? min(n[i-k], l-i) : ;
while (n[i]+i<l && c[n[i]] == c[n[i]+i]) n[i]++;
if (i+n[i]>p) p = i+n[i], k = i;
}
k = p = ;
rep(i, , l-)
{
ex[i] = i<p ? min(n[i-k], p-i) : ;
while (ex[i]+i<l && c[ex[i]] == s[ex[i]+i]) ex[i]++;
if (i+ex[i]>p) p = i+ex[i], k = i;
}
a = ; rep(i, , l-) { a+=t[s[l-i]-'a']; if (ex[l-i]==i) v[i]+=a; } rep(i, , l-) ex[i] = n[i] = ;
n[] = ; while (s[n[]] == s[n[]+]) n[]++;
n[] = l; k = ; p = n[];
rep(i, , l-)
{
n[i] = i<p ? min(n[i-k], p-i) : ;
while (n[i]+i<l && s[n[i]] == s[n[i]+i]) n[i]++;
if (i+n[i]>p) p = i+n[i], k = i;
}
k = p = ;
rep(i, , l-)
{
ex[i] = i<p ? min(n[i-k], p-i) : ;
while (ex[i]+i<l && s[ex[i]] == c[ex[i]+i]) ex[i]++;
if (i+ex[i]>p) p = i+ex[i], k = i;
}
a = ; rep(i, , l-) { a+=t[c[l-i]-'a']; if(ex[l-i]==i) v[l-i]+=a; } int ans = ; rep(i, , l-) ans = max(ans, v[i]); printf("%d\n", ans);
}
return ;
}

HDU 4333: Revolving Digits

扩展KMP的实例。。。

【代码莫名写WA了】

#include <cstdlib>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue> #define rep(i, l, r) for(int i = l; i <= r; i++)
#define down(i, l, r) for(int i = l; i >= r; i--)
#define ll long long
#define maxn 300009
#define MAX 1<<30
#define Q 1000000007 using namespace std; int tt, n[maxn];
char s[maxn]; int main()
{
scanf("%d", &tt); int t = ;
while (t++<tt)
{
scanf("%s", s); int l = strlen(s);
rep(i, , l-) s[l+i] = s[i];
int k, p;
n[] = l*; n[] = ; while (s[n[]] == s[n[]+]) n[]++; p = n[k=]+;
rep(i, , l-)
{
n[i] = i<p ? min(p-i, n[i-k]) : ;
while (s[n[i]] == s[n[i]+i]) n[i]++;
if (i+n[i]>p) p = i+n[i], k = i;
}
int q=, w=, e=;
rep(i, , l-) if (n[i]>=l) w++; else if (s[n[i]] < s[i+n[i]]) e++; else q++;
printf("Case %d: %d %d %d\n", t, q, w, e);
}
return ;
}

URAL 1297: Palindrome

第三道模板题。

#include <cstdlib>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue> #define rep(i, l, r) for(int i = l; i <= r; i++)
#define down(i, l, r) for(int i = l; i >= r; i--)
#define ll long long
#define maxn 2009
#define MAX 1<<30
#define Q 1000000007 using namespace std; int t, n, l, k[maxn], o, p, ans, b[maxn];
char c[maxn], s[maxn]; int main()
{
scanf("%s", c); l=strlen(c);
rep(i, , l-) s[i*+]='$', s[i*+]=c[i];
s[]='#'; s[*l+]='$';
ans = o = p = ;
rep(i, , l*+)
{
k[i] = i<p ? min(p-i, k[*o-i]) : ;
while (s[i+k[i]] == s[i-k[i]]) k[i]++;
if (i+k[i]>p) p = i+k[i], o = i;
if (k[ans]<k[i]) ans = i;
}
for(int i = ans-k[ans]+; i <= ans+k[ans]-; i+=) printf("%c", s[i]);
return ;
}

共8道题。

总之,Manacher、KMP和ExKMP所利用的就是之前已经计算过的信息,以减少无意义的匹配。

学习系列 - 马拉车&扩展KMP的更多相关文章

  1. MVC学习系列——ModelBinder扩展

    在MVC系统中,我们接受数据,运用的是ModelBinder 的技术. MVC学习系列——ActionResult扩展在这个系列中,我们自定义了XmlResult的返回结果. 那么是不是意味着能POS ...

  2. 学渣乱搞系列之扩展KMP的那点事

    扩展KMP牵涉了一些相对运动的姿势,比较费解!本学渣看了一天的扩展KMP,打算写点东西...本文看后,出现的后果本人一概不负责.毕竟我不是很会表达. 扩展KMP是搞什么灰机的?本学渣所知道的扩展KMP ...

  3. MVC学习系列——Filter扩展

    在MVC中,Filter也是可以扩展的.在此,本人对Filter的理解就是AOP,不知道各位大侠,有什么高的见解,呵呵... 首先MVC四大过滤神器IAuthorizationFilter,IActi ...

  4. MVC学习系列——RazorViewEngine扩展

    有时候,我们的项目涉及到多种风格,我们可以通过扩展RazorViewEngine,这样就可以保持后台代码不发生变化. 新建类ThemeViewEngine继承于RazorViewEngine publ ...

  5. MVC学习系列——ActionResult扩展

    首先,MVC扩展性非常强. 我从ActionResult扩展入手,因为我们知道微软ActionResult和其子类,有时候并不能满足所有返回值. 比如:我需要返回XML. 因此,现在我扩展XMLRes ...

  6. MVC学习系列——HtmlHelper扩展

    微软自带很多HtmlHelper: ActionLink - 链接到操作方法.BeginForm  - 标记窗体的开头并链接到呈现该窗体的操作方法.CheckBox  - 呈现复选框.DropDown ...

  7. LINQ学习系列-----1.3 扩展方法

    这篇内容继续接着昨天的Lambda表达式的源码继续下去.昨天讲了Lambda表达式,此篇讲扩展方法,这两点都是Linq带来的新特性.    一.扩展方法介绍   废话不多说,先上源码截图: 上图中Ge ...

  8. 【Silverlight】Bing Maps学习系列(六):使用扩展模式(Extended Modes)(转)

    [Silverlight]Bing Maps学习系列(六):使用扩展模式(Extended Modes) 微软Bing Maps推出有有段时间了,通过不断的改进和新的地图更新,现在已经基本上形成了一套 ...

  9. iOS学习系列 - 扩展机制category与associative

    iOS学习系列 - 扩展机制category与associative category与associative作为objective-c的扩展机制的两个特性,category即类型,可以通过它来扩展方 ...

随机推荐

  1. Objective-C Runtime Reference

    This document describes the OS X Objective-C 2.0 runtime library support functions and data structur ...

  2. C#调用CMD程序

    最近写了两个小程序都要调用Windows自带的命令行程序,一个是调用Openfiles.exe查询正在编辑的共享文档,一个是调用DiskPart.exe查询硬盘状态.两种命令行程序调用有点不同,记录一 ...

  3. ZOJ 3466 The Hive II (插头DP,变形)

    题意:有一个n*8的蜂房(6边形的格子),其中部分是障碍格子,其他是有蜂蜜的格子,每次必须走1个圈取走其中的蜂蜜,在每个格子只走1次,且所有蜂蜜必须取走,有多少种取法? 思路: 以前涉及的只是n*m的 ...

  4. codevs 3129 奶牛代理商IX

    时间限制: 1 s  空间限制: 32000 KB  题目等级 : 白银 Silver 题目描述 Description 小X从美国回来后,成为了USACO中国区的奶牛销售代理商,专门出售质优价廉的“ ...

  5. dataSource' defined in class path resource [org/springframework/boot/autocon

    spring boot启动的时候抛出如下异常: dataSource' defined in class path resource [org/springframework/boot/autocon ...

  6. 利用VS自带的命令行工具查看和生产PublicKeyToken

    使用VS2008(或其他版本)命令行工具,键入:SN -T C:\*****.dll 就会显示出该dll具体的PublicKeyToken数值. 如果该程序集没有强命 名,则不会有PublicKeyT ...

  7. git 不完全教程

    概念 工作目录:当前所见,Working directory 暂存区域:以后要提交到仓库的文件,称为Index或者staging area Git 仓库:持久化存储快照的地方,HEAD指针所指向的地方 ...

  8. [图文][提供可行性脚本] CentOS 7 Fencing+Pacemaker三节点搭建高可用集群

    实验说明: 实验环境: 宿主机系统   :Fedora 28 WorkStation 虚拟机管理器 :Virt-Manager 1.5.1 虚拟机配置   :ha1  CentOS 7.2 1511 ...

  9. Day11名称空间,作用域,闭包函数

    Day11 1.函数对象: ①可以被引用 ​ ②可以作为另一个函数的参数 ​ ③可以作为另一个函数的返回值0 ​ ④可以被存储到容器类型中 2.函数嵌套: ①嵌套调用:在一个函数中调用了另一个函数 ​ ...

  10. (原) 剑指offer--之数值的整数次方

    题目描述 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方.   初次看题觉得这题好简单,直接用库函数power()不就行了,仔细想了想,万 ...