题目来自:http://www.cnblogs.com/wuyiqi/archive/2012/01/06/2315188.html

KMP算法开始是判断字符串b是否是字符串a的子串,朴素的算法是枚举,时间复杂度O(m*n)

然后KMP(三个人名字的缩写)发明了KMP算法使时间复杂度降到了O(m+n)

但是<string.h>里面明明有一个函数是strstr(a,b)判断b是否为a的子串啊啊啊啊!!!

这个写得蛮好:http://blog.chinaunix.net/uid-27164517-id-3280128.html

以下仅限于个人理解:

a和b字符串匹配过程中,在j位置开始不匹配了

在0-j中寻找b0 b1 b2 ... bk = b(j-1-k) ... b(j-1)

当b与a字符串失配b应当从k+1个字符开始与a中刚刚失配的位置进行匹配

所以要确定k的值,而k的取值仅与j的位置有关,所以用next[]数组来盛放相应位置k的值

next(j) =   -1  起始位置

       k+1  0 <= k < j-1 失配时b应当重新开始匹配的位置

        0         其他

next[]数组的确立

  1. void getNext(){
  2. int k = -;
  3. next[] = -;
  4. int j = ;
  5. int len = strlen(str);
  6. while(j < len){
  7. if(k == - || str[j] == str[k]){
  8. k++;
  9. j++;
  10. next[j] = k;
  11. }
  12. else{
  13. k = next[k];
  14. }
  15. }
  16. }

http://poj.org/problem?id=3461

给a串和b串,求出b串中包含多少个a串

主要思路:

先对b进行next求解,然后对匹配到达最后进行计数……

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <cstdlib>
  7. #include <stack>
  8. #include <cctype>
  9. #include <string>
  10. #include <queue>
  11. #include <map>
  12. #include <set>
  13.  
  14. using namespace std;
  15.  
  16. const int INF = 0xffffff;
  17. const double ESP = 10e-;
  18. const double Pi = * atan(1.0);
  19. const int MAXN = + ;
  20. const long long MOD = ;
  21. const int dr[] = {,,-,,-,,-,};
  22. const int dc[] = {,,,-,,-,-,};
  23. typedef long long LL;
  24.  
  25. LL gac(LL a,LL b){
  26. return b?gac(b,a%b):a;
  27. }
  28. char str[+];
  29. char str1[MAXN];
  30. int next[+];
  31.  
  32. void getNext(){
  33. int k = -;
  34. int j = ;
  35. next[] = -;
  36. int len = strlen(str);
  37. while(j < len){
  38. if(k == - || str[j] == str[k]){
  39. j++;
  40. k++;
  41. next[j] = k;
  42. }
  43. else{
  44. k = next[k];
  45. }
  46. }
  47. }
  48.  
  49. int main()
  50. {
  51. #ifndef ONLINE_JUDGE
  52. freopen("inpt.txt","r",stdin);
  53. // freopen("output.txt","w",stdout);
  54. #endif
  55. int t;
  56. scanf("%d",&t);
  57. while(t--){
  58. scanf("%s%s",str,str1);
  59. getNext();
  60. int cnt = ;
  61. int len = strlen(str);
  62. int len1 = strlen(str1);
  63. int j = ;
  64. int i = ;
  65. while(i < len1){
  66. if(j == - || str[j] == str1[i]){
  67. i++;
  68. j++;
  69. }
  70. else{
  71. j = next[j];
  72. }
  73. if(j == len){
  74. cnt++;
  75. }
  76. }
  77. printf("%d\n",cnt);
  78. }
  79. return ;
  80. }

http://poj.org/problem?id=2406

给你一个字符串s要求求出最大的 n 使 s = a^n (a是字串)

主要思路:

先对s串进行next求解,然后如果 len % (len-next[len]) == 0说明字符串恰由子串的n次方组成

则结果是  len / (len-next[len])

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <algorithm>
  6.  
  7. using namespace std;
  8. const int MAXN = 10e6 + ;
  9. const int ESP = 10e-;
  10.  
  11. char str[MAXN];
  12. int next[MAXN];
  13.  
  14. void getNext(){
  15. int k = -;
  16. next[] = -;
  17. int j = ;
  18. int len = strlen(str);
  19. while(j < len){
  20. if(k == - || str[j] == str[k]){
  21. k++;
  22. j++;
  23. next[j] = k;
  24. }
  25. else{
  26. k = next[k];
  27. }
  28. }
  29. }
  30.  
  31. int main(){
  32. // freopen("input.txt","r",stdin);
  33. while(~scanf("%s",str)){
  34. if(str[] == '.')
  35. break;
  36. getNext();
  37. int len = strlen(str);
  38. if(len % (len - next[len]) == ){
  39. printf("%d\n",len / (len - next[len]));
  40. }
  41. else{
  42. printf("1\n");
  43. }
  44. }
  45. return ;
  46. }

http://poj.org/problem?id=2752

给你一个字符串s,要求求出字符串从头开始到某个位置形成的子串a和从后面的某个位置到结尾的子串b,完全相同时输出a串的长度

主要思路:

先对s串进行next求解,从结尾开始依次寻找next[j] != 0 这说明最后几个和开头肯定是相同的,所以最后输出就好,ps:s串本身也符合条件

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <algorithm>
  6.  
  7. using namespace std;
  8. const int MAXN = + ;
  9. const int ESP = 10e-;
  10.  
  11. char str[MAXN];
  12. int next[MAXN];
  13. int q[MAXN];
  14.  
  15. void getNext(){
  16. int k = -;
  17. next[] = -;
  18. int j = ;
  19. int len = strlen(str);
  20. while(j < len){
  21. if(k == - || str[j] == str[k]){
  22. k++;
  23. j++;
  24. next[j] = k;
  25. }
  26. else{
  27. k = next[k];
  28. }
  29. }
  30. }
  31.  
  32. int main(){
  33. // freopen("input.txt","r",stdin);
  34. while(~scanf("%s",str)){
  35. memset(next,,sizeof(next));
  36. getNext();
  37. int len = strlen(str);
  38. int cnt = ;
  39. int k = next[len];
  40. q[cnt++] = len;
  41. while(k){
  42. q[cnt++] = k;
  43. k = next[k];
  44. }
  45. for(int i = cnt-;i >= ;i--){
  46. if(i != cnt-)
  47. cout << ' ';
  48. cout << q[i];
  49. }
  50. cout << endl;
  51. }
  52. return ;
  53. }

http://poj.org/problem?id=2185

给你一个字符串矩阵,求出最小的子矩阵能把矩阵完全覆盖,求其面积

主要思路:

对字符矩阵的每行,每列进行next求解,求得其最小的字串能把所代表的字符串覆盖掉,得到行的最小公倍数,和列的最小公倍数,然后相乘求出面积。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <cstdlib>
  7. #include <stack>
  8. #include <cctype>
  9. #include <string>
  10. #include <queue>
  11. #include <map>
  12. #include <set>
  13.  
  14. using namespace std;
  15.  
  16. const int INF = 0xffffff;
  17. const double ESP = 10e-;
  18. const double Pi = * atan(1.0);
  19. const int MAXN = + ;
  20. const long long MOD = ;
  21. const int dr[] = {,,-,,-,,-,};
  22. const int dc[] = {,,,-,,-,-,};
  23. typedef long long LL;
  24.  
  25. LL gac(LL a,LL b){
  26. return b?gac(b,a%b):a;
  27. }
  28. int lcm(int i,int j){
  29. return i * j / gac(i,j);
  30. }
  31. char str[MAXN][];
  32. int next[MAXN];
  33. int n,m;
  34.  
  35. void getR(int i){
  36. int j = ;
  37. int k = -;
  38. next[] = -;
  39. while(j < m){
  40. if(k == - || str[i][j] == str[i][k]){
  41. j++;
  42. k++;
  43. next[j] = k;
  44. }
  45. else{
  46. k = next[k];
  47. }
  48. }
  49. }
  50.  
  51. void getC(int i){
  52. int j = ;
  53. int k = -;
  54. next[] = -;
  55. while(j < n){
  56. if(k == - || str[j][i] == str[k][i]){
  57. j++;
  58. k++;
  59. next[j] = k;
  60. }
  61. else{
  62.  
  63. k = next[k];
  64. }
  65. }
  66. }
  67.  
  68. int main()
  69. {
  70. #ifndef ONLINE_JUDGE
  71. freopen("inpt.txt","r",stdin);
  72. // freopen("output.txt","w",stdout);
  73. #endif
  74. while(~scanf("%d%d",&n,&m)){
  75. for(int i = ;i < n;i++){
  76. scanf("%s",str[i]);
  77. }
  78. int r = ;
  79. int c = ;
  80. for(int i = ;i < n;i++){
  81. getR(i);
  82. int t = m - next[m];
  83. r = lcm(r,t);
  84. if(r >= m){
  85. r = m;
  86. break;
  87. }
  88. }
  89. for(int i = ;i < m;i++){
  90. getC(i);
  91. int t = n - next[n];
  92. c = lcm(c,t);
  93. if(c >= n){
  94. c = n;
  95. break;
  96. }
  97. }
  98.  
  99. printf("%d\n",r*c);
  100. }
  101. return ;
  102. }

http://poj.org/problem?id=3080

求给出字符串共同拥有的字典序最小的长度最长的子串

解题思路:暴力,strstr函数直接水掉……2333333

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4.  
  5. using namespace std;
  6.  
  7. char dna[][];
  8. char str[];
  9. char str1[];
  10.  
  11. int main()
  12. {
  13. // freopen("input.in","r",stdin);
  14. int t;
  15. int m;
  16. scanf("%d",&t);
  17. while(t--)
  18. {
  19. scanf("%d",&m);
  20. for(int i = ;i < m;i++)
  21. scanf("%s",dna[i]);
  22. int maxnum = -0xfffff;
  23. int len = strlen(dna[]);
  24. bool flag = true;
  25. for(int i = ;i < len;i++)
  26. {
  27. memset(str,,sizeof(str));
  28. int t = ;
  29. for(int j = ;j < len;j++)
  30. {
  31. bool flag2 = true;
  32. if(i+j >= len)
  33. break;
  34. str[j] = dna[][i+j];
  35. for(int k = ;k < m;k++)
  36. {
  37. if(strstr(dna[k],str) == NULL)
  38. {
  39. flag2 = false;
  40. break;
  41. }
  42. }
  43. if(flag2)
  44. {
  45. t++;
  46. if(t == maxnum)
  47. {
  48. if(strcmp(str1,str) > )
  49. strcpy(str1,str);
  50. }
  51. if(t > maxnum)
  52. {
  53. maxnum = t;
  54. strcpy(str1,str);
  55. }
  56. flag = false;
  57. }
  58. else
  59. break;
  60. }
  61. }
  62. if(maxnum < || flag)
  63. printf("no significant commonalities\n");
  64. else
  65. {
  66. printf("%s\n",str1);
  67. }
  68. }
  69. return ;
  70. }

KMP poj的更多相关文章

  1. 字符串专题:KMP POJ 3561

    http://poj.org/problem?id=3461 KMP这里讲的不错next的求法值得借鉴 http://blog.sina.com.cn/s/blog_70bab9230101g0qv. ...

  2. 字符串KMP || POJ 2185 Milking Grid

    求一个最小矩阵,经过复制能够覆盖原矩阵(覆盖,不是填充,复制之后可以有多的) *解法:横着竖着kmp,求最大公倍数的做法是不对的,见http://blog.sina.com.cn/s/blog_69c ...

  3. KMP POJ 1961 Period

    题目传送门 /* 题意:求一个串重复出现(>1)的位置 KMP:这简直和POJ_2406没啥区别 */ /******************************************** ...

  4. KMP POJ 2406 Power Strings

    题目传送门 /* 题意:一个串有字串重复n次产生,求最大的n KMP:nex[]的性质应用,感觉对nex加深了理解 */ /************************************** ...

  5. KMP POJ 2752 Seek the Name, Seek the Fame

    题目传送门 /* 题意:求出一个串的前缀与后缀相同的字串的长度 KMP:nex[]就有这样的性质,倒过来输出就行了 */ /************************************** ...

  6. Kuangbin 带你飞 KMP扩展KMP Manacher

    首先是几份模版 KMP void kmp_pre(char x[],int m,int fail[]) { int i,j; j = fail[] = -; i = ; while (i < m ...

  7. POJ 3450 后缀数组/KMP

    题目链接:http://poj.org/problem?id=3450 题意:给定n个字符串,求n个字符串的最长公共子串,无解输出IDENTITY LOST,否则最长的公共子串.有多组解时输出字典序最 ...

  8. POJ 2406 KMP/后缀数组

    题目链接:http://poj.org/problem?id=2406 题意:给定一个字符串,求由一个子串循环n次后可得到原串,输出n[即输出字符串的最大循环次数] 思路一:KMP求最小循环机,然后就 ...

  9. 【poj 2185】Milking Grid(字符串--KMP+问题分解)

    题意:给定一个由字符组成的矩阵,求出它的面积最小的覆盖矩阵.(感觉应该是可重叠的......* (・ω・)っ) 解法:KMP.行列互不影响,可以问题分解.先求出每一行的最小重复串,利用kmp中的nex ...

随机推荐

  1. jquey的 ajax请求的几种方式

    在jquery中,提供了集中方法来进行ajax操作 一.$.get(url,[data],[callback]) 向服务器发起get操作. 说明:url为请求地址,data为请求数据的列表(json对 ...

  2. 进入MFC讲坛的前言(三)

    MFC中的窗口创建及窗口消息映射 我经常碰到有人问我有关窗口创建的问题,他们经常把用HWND描述的系统窗口对象和用CWnd描述的MFC的窗口对象混淆不清.这两者之间是紧密联系在一起的,但是MFC为了自 ...

  3. (未解决)在JSTL中,session 和 sessionScope 有什么区别 ??

    在JSP页面中,使用JSTL标签获取Session中的值并显示 为何当使用 ${session.user} 时,页面跳转后,第一次能够成功显示, 但是单击按钮重定向的时候,就获取不到了? 而使用 ${ ...

  4. SICP练习1.6-1.8

    1.6 死循环 1.7 #lang racket (define (square x) (* x x)) (define (sqrt-iter guess x) (if (good-enough? g ...

  5. javascript每日一练(十三)——运动实例

    一.图片放大缩小 <!doctype html> <html> <head> <meta charset="utf-8"> < ...

  6. 一天一个类,一点也不累 之 LinkedList

    我们的口号是,一天一个类,一点也不累 .. 今天要讲的是---LinkedList 首先,还是看看他的组织结构 Class LinkedList<E> java.lang.Object j ...

  7. 彻底明白Java的IO系统

    java学习:彻底明白Java的IO系统 文章来源:互联网 一. Input和Output1. stream代表的是任何有能力产出数据的数据源,或是任何有能力接收数据的接收源.在Java的IO中,所有 ...

  8. Cocos2d-X游戏开发之Windows7+VS2010环境搭建(亲测)

    Cocos2d—X游戏引擎,提供Mac系统下的Xcode开发和Windows系统的VS开发,应该是比较常用的2种. 使用Mac以后,就会发现使用Xcode开发实在是福分啊.VS开发步骤繁琐,调试效率低 ...

  9. Java I/O流-ObjectInputStream、ObjectOutputStream

    一.整体代码 ObjectStreamDemo.java import java.io.File; import java.io.FileInputStream; import java.io.Fil ...

  10. rackup工具

    gem包rack提供了rackup工具来启动webapplication 下面是一个入门范例,使用 bundler 管理库的一个sinatra应用   在begin文件夹下有三个文件 begin.ru ...