学习系列 - 马拉车&扩展KMP
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的更多相关文章
- MVC学习系列——ModelBinder扩展
在MVC系统中,我们接受数据,运用的是ModelBinder 的技术. MVC学习系列——ActionResult扩展在这个系列中,我们自定义了XmlResult的返回结果. 那么是不是意味着能POS ...
- 学渣乱搞系列之扩展KMP的那点事
扩展KMP牵涉了一些相对运动的姿势,比较费解!本学渣看了一天的扩展KMP,打算写点东西...本文看后,出现的后果本人一概不负责.毕竟我不是很会表达. 扩展KMP是搞什么灰机的?本学渣所知道的扩展KMP ...
- MVC学习系列——Filter扩展
在MVC中,Filter也是可以扩展的.在此,本人对Filter的理解就是AOP,不知道各位大侠,有什么高的见解,呵呵... 首先MVC四大过滤神器IAuthorizationFilter,IActi ...
- MVC学习系列——RazorViewEngine扩展
有时候,我们的项目涉及到多种风格,我们可以通过扩展RazorViewEngine,这样就可以保持后台代码不发生变化. 新建类ThemeViewEngine继承于RazorViewEngine publ ...
- MVC学习系列——ActionResult扩展
首先,MVC扩展性非常强. 我从ActionResult扩展入手,因为我们知道微软ActionResult和其子类,有时候并不能满足所有返回值. 比如:我需要返回XML. 因此,现在我扩展XMLRes ...
- MVC学习系列——HtmlHelper扩展
微软自带很多HtmlHelper: ActionLink - 链接到操作方法.BeginForm - 标记窗体的开头并链接到呈现该窗体的操作方法.CheckBox - 呈现复选框.DropDown ...
- LINQ学习系列-----1.3 扩展方法
这篇内容继续接着昨天的Lambda表达式的源码继续下去.昨天讲了Lambda表达式,此篇讲扩展方法,这两点都是Linq带来的新特性. 一.扩展方法介绍 废话不多说,先上源码截图: 上图中Ge ...
- 【Silverlight】Bing Maps学习系列(六):使用扩展模式(Extended Modes)(转)
[Silverlight]Bing Maps学习系列(六):使用扩展模式(Extended Modes) 微软Bing Maps推出有有段时间了,通过不断的改进和新的地图更新,现在已经基本上形成了一套 ...
- iOS学习系列 - 扩展机制category与associative
iOS学习系列 - 扩展机制category与associative category与associative作为objective-c的扩展机制的两个特性,category即类型,可以通过它来扩展方 ...
随机推荐
- 查找算法(顺序查找、二分法查找、二叉树查找、hash查找)
查找功能是数据处理的一个基本功能.数据查找并不复杂,但是如何实现数据又快又好地查找呢?前人在实践中积累的一些方法,值得我们好好学些一下.我们假定查找的数据唯一存在,数组中没有重复的数据存在. (1)顺 ...
- 闹心的CSDN
近来搜索技术文章时,每次来到csdn上时,显示全文就提示登陆. 唉登陆就登陆吧,记不清账号了,就用手机号获取验证码.然后更改密码.我靠,密码居然要8位以上,要有大小写字母.数字和标点符号的组合... ...
- 再用python写一个文本处理的东东
朋友遇到一点麻烦,我自告奋勇帮忙.事情是这样的: - 他们的业务系统中,数据来自一个邮箱: - 每一个邮件包含一条记录: - 这些记录是纯文本的,字段之间由一些特殊字符分隔: - 他们需要从邮箱中批量 ...
- asp.net core mvc 异步表单(Ajax.BeginForm)
.net core中已经没有beginform扩展函数了. 通过Bower引入jquery-ajax-unobtrusive: <script src="~/lib/jquery-aj ...
- WebStorm 配置less
1.打开Webstorm的Setting 搜索,watch 找到 File watch,点击右侧加号添加Less. 2.配置, working directory. Output paths
- UVA 1220 Party at Hali-Bula (树形DP)
求一棵数的最大独立集结点个数并判断方案是否唯一. dp[i][j]表示以i为根的子树的最大独立集,j的取值为选和不选. 决策: 当选择i时,就不能选择它的子结点. 当不选i时,它的子结点可选可不选. ...
- w3 parse a url
最新链接:https://www.w3.org/TR/html53/ 2.6 URLs — HTML5 li, dd li { margin: 1em 0; } dt, dfn { font-wei ...
- GIMP选择区域Selection Editor
如图我要选择该图的衣服部分和这个球的部分, 选择Select下的Selection Editor工具,然后点击魔法棒工具(Fuzzy Select Tool),选择衣服: 需要注意以下白色部分是选择的 ...
- C++简单年月日的功能实现
// C++年月日判断初步代码 #include <iostream> using namespace std; class Data { int year; int month; int ...
- CSS3-::selection
“::selection”只能设置两个属性,一个就是background,另一个就是color属性,设置其他属性是没有任何效果的. ::selection使用语法: /*Webkit,Opera9.5 ...