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. pingall脚本

    p i n g a l l:一个按照/ e t c / h o s t s文件中的条目逐一p i n g所有主机的脚本 它能够按照/ e t c / h o s t s文件中的条目逐一p i n g所 ...

  2. SIT&UAT

  3. 洛谷 P2419 [USACO08JAN]牛大赛Cow Contest

    题目背景 [Usaco2008 Jan] 题目描述 N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a p ...

  4. 洛谷 P1732 活蹦乱跳的香穗子

    题目描述 香穗子在田野上调蘑菇!她跳啊跳,发现自己很无聊,于是她想了一个有趣的事情,每个格子最多只能经过1次,且每个格子都有其价值 跳的规则是这样的,香穗子可以向上下左右四个方向跳到相邻的格子,并且她 ...

  5. Java-NestedClass(Interface).

    内部类(Nested Class) 内部类:即在一个类中还包含着另外一个类,一般是作为匿名类或者是使用数据隐藏时使用的.例子: //内部类 class Out{ private int age = 1 ...

  6. 1658: Easier Done Than Said?

    1658: Easier Done Than Said? Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 15  Solved: 12[Submit][St ...

  7. 二分查找 && 三分查找

    LeetCode34. Find First and Last Position of Element in Sorted Array 题意:找出指定元素出现的范围,Ologn 思路:两次二分 cla ...

  8. mysql 特定查询条件下导致的大海捞针

    order表: order type  gmt_create type 取值: 0,1  其中0非常多,1非常少. 当查询条件里 select * from order where type=0 an ...

  9. javaEE(3)_servlet基础

    一.Servlet简介 1.Servlet是sun公司提供的一门用于开发动态web资源的技术,Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序 ...

  10. 使用Auto Layout中的VFL(Visual format language)--代码实现自动布局

    使用Auto Layout中的VFL(Visual format language)--代码实现自动布局 2014-12-09 10:56 编辑: zhiwupei 分类:iOS开发 来源:机智的新手 ...