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

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


题目:

POJ 1159: Palindrome

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

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

  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <cmath>
  8. #include <queue>
  9.  
  10. #define rep(i, l, r) for(int i = l; i <= r; i++)
  11. #define down(i, l, r) for(int i = l; i >= r; i--)
  12. #define ll long long
  13. #define maxn 10009
  14. #define MAX 1<<30
  15. #define Q 1000000007
  16.  
  17. using namespace std;
  18.  
  19. int n, dp[][];
  20. char s[];
  21.  
  22. int main()
  23. {
  24. scanf("%d%s", &n, s);
  25. rep(i, , n) rep(j, , n)
  26. {
  27. dp[i%][j] = max(dp[(i-)%][j], dp[i%][j-]);
  28. if (s[i-]==s[n-j] && dp[(i-)%][j-]+>dp[i%][j]) dp[i%][j] = dp[(i-)%][j-]+;
  29. }
  30. printf("%d\n", n-dp[n%][n]);
  31. return ;
  32. }

HDU 3068: 最长回文

模板题。

  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <cmath>
  8. #include <queue>
  9.  
  10. #define rep(i, l, r) for(int i = l; i <= r; i++)
  11. #define down(i, l, r) for(int i = l; i >= r; i--)
  12. #define ll long long
  13. #define maxn 234567
  14. #define MAX 1<<30
  15. #define Q 1000000007
  16.  
  17. using namespace std;
  18.  
  19. int n, l, k[maxn], o, p, ans;
  20. char c[maxn], s[maxn];
  21.  
  22. int main()
  23. {
  24. while (scanf("%s", c) == )
  25. {
  26. l = strlen(c);
  27. rep(i, , l-) s[i*+] = '$', s[i*+] = c[i];
  28. l = l*+; s[l]=s[l+] = '$'; s[] = '#';
  29. o=p=ans=;
  30. rep(i, , l)
  31. {
  32. k[i] = i<p ? min(k[*o-i], p-i) : ;
  33. while (s[i+k[i]] == s[i-k[i]]) k[i]++;
  34. if (i+k[i]>p) p = i+k[i], o = i;
  35. ans = max(ans, k[i]-);
  36. }
  37. printf("%d\n", ans);
  38. }
  39. return ;
  40. }

POJ 3974: Palindrome

同模板题。

  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <cmath>
  8. #include <queue>
  9.  
  10. #define rep(i, l, r) for(int i = l; i <= r; i++)
  11. #define down(i, l, r) for(int i = l; i >= r; i--)
  12. #define ll long long
  13. #define maxn 2000009
  14. #define MAX 1<<30
  15. #define Q 1000000007
  16.  
  17. using namespace std;
  18.  
  19. int t, n, l, k[maxn], o, p, ans;
  20. char c[maxn], s[maxn];
  21.  
  22. int main()
  23. {
  24. while (++t)
  25. {
  26. scanf("%s", c);
  27. if (c[]=='E') break; l = strlen(c);
  28. rep(i, , l-) s[i*+]='$', s[i*+]=c[i];
  29. l=l*+; s[]='#'; s[l]=s[l+]='$';
  30. ans=o=p=;
  31. rep(i, , l)
  32. {
  33. k[i] = i<p ? min(p-i, k[o*-i]) : ;
  34. while (s[i+k[i]] == s[i-k[i]]) k[i]++;
  35. if (i+k[i]>p) p=i+k[i], o=i;
  36. ans = max(ans, k[i]-);
  37. }
  38. printf("Case %d: %d\n", t, ans);
  39. }
  40. return ;
  41. }

BZOJ 2342: 双倍回文

求最长双倍回文。

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

  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <cmath>
  8. #include <queue>
  9.  
  10. #define rep(i, l, r) for(int i = l; i <= r; i++)
  11. #define down(i, l, r) for(int i = l; i >= r; i--)
  12. #define ll long long
  13. #define maxn 1000009
  14. #define MAX 1<<30
  15. #define Q 1000000007
  16.  
  17. using namespace std;
  18.  
  19. int t, n, l, k[maxn], o, p, ans, b[maxn];
  20. char c[maxn], s[maxn];
  21.  
  22. int main()
  23. {
  24. scanf("%d%s", &l, c);
  25. rep(i, , l-) s[i*+]='$', s[i*+]=c[i];
  26. s[]='#'; s[l*+]='$';
  27. ans=o=p=;
  28. rep(i, , l*+)
  29. {
  30. k[i] = i<p ? min(p-i, k[o*-i]) : ;
  31. while (s[i+k[i]] == s[i-k[i]]) k[i]++;
  32. if (i+k[i]>p) p=i+k[i], o=i;
  33. }
  34. rep(i, , l) b[i+]=k[i*-]/;
  35. rep(i, , l)
  36. down(j, b[i]/, ans+) if (b[i-j]>=j && b[i+j]>=j) ans = j;
  37. printf("%d\n", ans*);
  38. return ;
  39. }

BZOJ 2565: 最长双回文串

求最长双回文串。

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

  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <cmath>
  8. #include <queue>
  9.  
  10. #define rep(i, l, r) for(int i = l; i <= r; i++)
  11. #define down(i, l, r) for(int i = l; i >= r; i--)
  12. #define ll long long
  13. #define maxn 200009
  14. #define MAX 1<<30
  15. #define Q 1000000007
  16.  
  17. using namespace std;
  18.  
  19. int t, n, l, k[maxn], o, p, ans, lt[maxn], rt[maxn];
  20. char c[maxn], s[maxn];
  21.  
  22. int main()
  23. {
  24. scanf("%s", c); l=strlen(c);
  25. rep(i, , l-) s[i*+]='$', s[i*+]=c[i];
  26. s[]='#'; s[*l+]='$';
  27. o = p = ;
  28. rep(i, , l*+)
  29. {
  30. k[i] = i<p ? min(p-i, k[*o-i]) : ;
  31. while (s[i+k[i]] == s[i-k[i]]) k[i]++;
  32. if (i+k[i]>p) p = i+k[i], o = i;
  33. }
  34. o = ; rep(i, , l*+)
  35. {
  36. while (o+k[o]<=i) o++;
  37. lt[i] = i-o;
  38. }
  39. o = l*+; down(i, l*, )
  40. {
  41. while (i<=o-k[o]) o--;
  42. rt[i] = o-i;
  43. }
  44. rep(i, , l*+) if (s[i]=='$' && lt[i] && rt[i] && ans < lt[i]+rt[i]) ans = lt[i]+rt[i];
  45. printf("%d\n", ans);
  46. return ;
  47. }

HDU 3613: Best Reward

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

  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <cmath>
  8. #include <queue>
  9.  
  10. #define rep(i, l, r) for(int i = l; i <= r; i++)
  11. #define down(i, l, r) for(int i = l; i >= r; i--)
  12. #define ll long long
  13. #define maxn 500009
  14. #define MAX 1<<30
  15. #define Q 1000000007
  16.  
  17. using namespace std;
  18.  
  19. int tt, l, n[maxn], ex[maxn], v[maxn], t[];
  20. char c[maxn], s[maxn];
  21.  
  22. int main()
  23. {
  24. scanf("%d", &tt);
  25. while (tt--)
  26. {
  27. rep(i, , ) scanf("%d", &t[i]);
  28. scanf("%s", s); int l = strlen(s);
  29. rep(i, , l-) c[i] = s[l-i-];
  30. int k, p, a; rep(i, , l-) v[i] = ;
  31.  
  32. rep(i, , l-) ex[i] = n[i] = ;
  33. n[] = ; while (c[n[]] == c[n[]+]) n[]++;
  34. n[] = l; k = ; p = n[];
  35. rep(i, , l-)
  36. {
  37. n[i] = i<p ? min(n[i-k], l-i) : ;
  38. while (n[i]+i<l && c[n[i]] == c[n[i]+i]) n[i]++;
  39. if (i+n[i]>p) p = i+n[i], k = i;
  40. }
  41. k = p = ;
  42. rep(i, , l-)
  43. {
  44. ex[i] = i<p ? min(n[i-k], p-i) : ;
  45. while (ex[i]+i<l && c[ex[i]] == s[ex[i]+i]) ex[i]++;
  46. if (i+ex[i]>p) p = i+ex[i], k = i;
  47. }
  48. a = ; rep(i, , l-) { a+=t[s[l-i]-'a']; if (ex[l-i]==i) v[i]+=a; }
  49.  
  50. rep(i, , l-) ex[i] = n[i] = ;
  51. n[] = ; while (s[n[]] == s[n[]+]) n[]++;
  52. n[] = l; k = ; p = n[];
  53. rep(i, , l-)
  54. {
  55. n[i] = i<p ? min(n[i-k], p-i) : ;
  56. while (n[i]+i<l && s[n[i]] == s[n[i]+i]) n[i]++;
  57. if (i+n[i]>p) p = i+n[i], k = i;
  58. }
  59. k = p = ;
  60. rep(i, , l-)
  61. {
  62. ex[i] = i<p ? min(n[i-k], p-i) : ;
  63. while (ex[i]+i<l && s[ex[i]] == c[ex[i]+i]) ex[i]++;
  64. if (i+ex[i]>p) p = i+ex[i], k = i;
  65. }
  66. a = ; rep(i, , l-) { a+=t[c[l-i]-'a']; if(ex[l-i]==i) v[l-i]+=a; }
  67.  
  68. int ans = ; rep(i, , l-) ans = max(ans, v[i]); printf("%d\n", ans);
  69. }
  70. return ;
  71. }

HDU 4333: Revolving Digits

扩展KMP的实例。。。

【代码莫名写WA了】

  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <cmath>
  8. #include <queue>
  9.  
  10. #define rep(i, l, r) for(int i = l; i <= r; i++)
  11. #define down(i, l, r) for(int i = l; i >= r; i--)
  12. #define ll long long
  13. #define maxn 300009
  14. #define MAX 1<<30
  15. #define Q 1000000007
  16.  
  17. using namespace std;
  18.  
  19. int tt, n[maxn];
  20. char s[maxn];
  21.  
  22. int main()
  23. {
  24. scanf("%d", &tt); int t = ;
  25. while (t++<tt)
  26. {
  27. scanf("%s", s); int l = strlen(s);
  28. rep(i, , l-) s[l+i] = s[i];
  29. int k, p;
  30. n[] = l*; n[] = ; while (s[n[]] == s[n[]+]) n[]++; p = n[k=]+;
  31. rep(i, , l-)
  32. {
  33. n[i] = i<p ? min(p-i, n[i-k]) : ;
  34. while (s[n[i]] == s[n[i]+i]) n[i]++;
  35. if (i+n[i]>p) p = i+n[i], k = i;
  36. }
  37. int q=, w=, e=;
  38. rep(i, , l-) if (n[i]>=l) w++; else if (s[n[i]] < s[i+n[i]]) e++; else q++;
  39. printf("Case %d: %d %d %d\n", t, q, w, e);
  40. }
  41. return ;
  42. }

URAL 1297: Palindrome

第三道模板题。

  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <cstring>
  7. #include <cmath>
  8. #include <queue>
  9.  
  10. #define rep(i, l, r) for(int i = l; i <= r; i++)
  11. #define down(i, l, r) for(int i = l; i >= r; i--)
  12. #define ll long long
  13. #define maxn 2009
  14. #define MAX 1<<30
  15. #define Q 1000000007
  16.  
  17. using namespace std;
  18.  
  19. int t, n, l, k[maxn], o, p, ans, b[maxn];
  20. char c[maxn], s[maxn];
  21.  
  22. int main()
  23. {
  24. scanf("%s", c); l=strlen(c);
  25. rep(i, , l-) s[i*+]='$', s[i*+]=c[i];
  26. s[]='#'; s[*l+]='$';
  27. ans = o = p = ;
  28. rep(i, , l*+)
  29. {
  30. k[i] = i<p ? min(p-i, k[*o-i]) : ;
  31. while (s[i+k[i]] == s[i-k[i]]) k[i]++;
  32. if (i+k[i]>p) p = i+k[i], o = i;
  33. if (k[ans]<k[i]) ans = i;
  34. }
  35. for(int i = ans-k[ans]+; i <= ans+k[ans]-; i+=) printf("%c", s[i]);
  36. return ;
  37. }

共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. 查找算法(顺序查找、二分法查找、二叉树查找、hash查找)

    查找功能是数据处理的一个基本功能.数据查找并不复杂,但是如何实现数据又快又好地查找呢?前人在实践中积累的一些方法,值得我们好好学些一下.我们假定查找的数据唯一存在,数组中没有重复的数据存在. (1)顺 ...

  2. 闹心的CSDN

    近来搜索技术文章时,每次来到csdn上时,显示全文就提示登陆. 唉登陆就登陆吧,记不清账号了,就用手机号获取验证码.然后更改密码.我靠,密码居然要8位以上,要有大小写字母.数字和标点符号的组合... ...

  3. 再用python写一个文本处理的东东

    朋友遇到一点麻烦,我自告奋勇帮忙.事情是这样的: - 他们的业务系统中,数据来自一个邮箱: - 每一个邮件包含一条记录: - 这些记录是纯文本的,字段之间由一些特殊字符分隔: - 他们需要从邮箱中批量 ...

  4. asp.net core mvc 异步表单(Ajax.BeginForm)

    .net core中已经没有beginform扩展函数了. 通过Bower引入jquery-ajax-unobtrusive: <script src="~/lib/jquery-aj ...

  5. WebStorm 配置less

    1.打开Webstorm的Setting 搜索,watch 找到 File watch,点击右侧加号添加Less. 2.配置, working directory. Output paths

  6. UVA 1220 Party at Hali-Bula (树形DP)

    求一棵数的最大独立集结点个数并判断方案是否唯一. dp[i][j]表示以i为根的子树的最大独立集,j的取值为选和不选. 决策: 当选择i时,就不能选择它的子结点. 当不选i时,它的子结点可选可不选. ...

  7. w3 parse a url

     最新链接:https://www.w3.org/TR/html53/ 2.6 URLs — HTML5 li, dd li { margin: 1em 0; } dt, dfn { font-wei ...

  8. GIMP选择区域Selection Editor

    如图我要选择该图的衣服部分和这个球的部分, 选择Select下的Selection Editor工具,然后点击魔法棒工具(Fuzzy Select Tool),选择衣服: 需要注意以下白色部分是选择的 ...

  9. C++简单年月日的功能实现

    // C++年月日判断初步代码 #include <iostream> using namespace std; class Data { int year; int month; int ...

  10. CSS3-::selection

    “::selection”只能设置两个属性,一个就是background,另一个就是color属性,设置其他属性是没有任何效果的. ::selection使用语法: /*Webkit,Opera9.5 ...