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. linux服务器上的jenkins远程触发构建windows server 2012服务器上的jenkins任务

    本文来自:https://blog.csdn.net/huashao0602/article/details/53318295  非常感谢原博主,亲测可行,这是我做CI持续集成试过的第6套方案了! 背 ...

  2. [windows]命令行关机或重启电脑

    1.关机:菜单--〉运行--〉输入:cmd--〉输入:shutdown -s -t 0 2.重启:菜单--〉运行--〉输入:cmd--〉输入:shutdown -r -t 0 (注:“-r”代表重启, ...

  3. 大数据freestyle: 共享单车轨迹数据助力城市合理规划自行车道

    编者按:近年来,异军突起的共享单车极大地解决了人们共同面临的“最后一公里”难题,然而,共享单车发展迅猛,自行车道建设却始终没有能够跟上脚步.幸运的是摩拜单车大量的轨迹数据为我们提供了一种新的思路:利用 ...

  4. kettle数据同步方法

    1.实时性要求不高,采用全删全插的方式(适合于维度表.大数据量表) 2.有时间维度,直接从事实表同步的数据,可以采用根据时间字段进行筛选,增量同步.这个网上有很多例子,就不重复写了. 3.没有时间维度 ...

  5. App Store中的开源游戏汇总

    这是国外达人收集的曾经在app store上出现过,或者还在app store上卖的iOS开源游戏的列表,其中代码大部分人你托管在google code或者github上,其中有很多使用Cocos2D ...

  6. Dijkstra算法——单源最短路算法

    一.介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他各个节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 适用于有 ...

  7. gitlab autuo devops

    [参考文章] Chengzi_comm的专栏 use gitlab ci docker run gitlab-runner gitlab-runner register 1. 在虚拟机或服务器运行gi ...

  8. 【Java_基础】并发、并行、同步、异步、多线程的区别

    1. 并发:位于同一个处理器上的多个已开启未完成的线程,在任意一时刻系统调度只能让一个线程获得CPU资源运行,虽然这种调度机制有多种形式(大多数是以时间片轮巡为主).但无论如何,都是通过不断切换需要运 ...

  9. Git学习——撤销修改

    git checkout -- <file> 当你修改完一个工作区的文件后,使用git status查看当前的状态.其中有说明,接下来你可以git add <file> 去添加 ...

  10. logging模块,程序日志模板

    6.11自我总结 1.logging模块 用于程序的运行日志 1.初级 #首先程序运行分会出现5中情况 1.logging.info('info') #程序正常运行级别为10 2.logging.de ...