HDU1358

http://acm.hdu.edu.cn/showproblem.php?pid=1358

先构造出 next[] 数组,下标为 i,定义一个变量 j = i - next[i] 就是next数组下标和下标对应值的差,如果这个差能整除下标 i,即 i%j==0 ,则说明下标i之前的字符串(周期性字符串长度为 i)一定可以由一个前缀周期性的表示出来,这个前缀的长度为刚才求得的那个差,即 j,则这个前缀出现的次数为 i/j 

#include <iostream>
#include <stdio.h>
using namespace std;
char a[1000010];
int next[1000010];
int n;
void GetNext()    //获得a数列的next数组
{int i=0,k=-1;next[0] = -1;while(i<n){if(k==-1){next[i+1] = 0;i++;k++;}else if(a[i]==a[k]){next[i+1] = k+1;i++;k++;}elsek = next[k];}
}
void DisRes(int num)
{int j;printf("Test case #%d\n",num);for(int i=0;i<=n;i++){if(next[i]==-1 || next[i]==0)   //next[i]是-1或0的忽略,说明之前没有周期性前缀continue;j = i - next[i];if(i%j==0)  //能整除,说明存在周期性前缀printf("%d %d\n",i,i/j);    //输出这个前缀的长度和周期数}printf("\n");
}
int main()
{int num = 0;while(scanf("%d",&n)!=EOF){if(n==0) break;scanf("%s",a);GetNext();  //获得next[]数组DisRes(++num);  //输出结果}return 0;
}

HUST 1010

http://www.hustoj.org/problem/1010

读错题了,B是减下来的那一堆,那就好做了。找最短循环节就可以了。(循环节:从某一位起向右进行到某一位止的一节数字循环出现,首尾衔接,称这种小数为循环小数,这一节数字称为循环节。)

#include<stdio.h>
#include<string.h>
#define N 1000005
char str[N];
int f[N];
void getFail(char *p, int *f)
{int m=strlen(p);f[0]=f[1]=0;for(int i=1; i<m; ++i){int j=f[i];while(j && p[i]!=p[j])j=f[j];f[i+1] = p[i]==p[j]?1+j:0;}
}
int main()
{while(scanf("%s",str)!=EOF){int len=strlen(str);getFail(str,f);printf("%d\n",len-f[len]);}return 0;
}

POJ 2406

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

大意:给出一个字符串 问它最多由多少相同的字串组成

如  abababab由4个ab组成

最小循环节

ababab  next[6] = 4; 即

ababab

ababab

1~4位  与2~6位是相同的

那么前两位

就等于3、4位

3、4位就等于5、6位

……

所以 如果 能整除  也就循环到最后了

如果不能整除

就最后余下的几位不在循环内

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;const int maxn = 1000005;int next[maxn];void get(char *s) {int l = strlen(s);int j = 0, k = -1;next[0] = -1;while(j < l) {if(k == -1 || s[j] == s[k]) {next[++j] = ++k;} else {k = next[k];}}
}
char s[maxn];int main() {while(gets(s) ) {if(strcmp(s,".") == 0) {break;}get(s);int ans = 1;int l = strlen(s);if(l % (l - next[l]) == 0) {ans = l / (l - next[l]);}printf("%d\n", ans);}
}

POJ2752

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

大意:给定字符串S,求出S的所有可能相同前后缀的长度。比如: 
"alala"的前缀分别为{"a", "al", "ala", "alal", "alala"}, 后缀分别为{"a", "la", "ala", "lala", "alala"}. 其中有{"a", "ala", "alala"}是相同的,即输入1,3,5.

思路:有了kmp算法的next数组(保存某段子串的相同前后缀的最大长度,不包括自身),可以从最长的相同前后缀开始考虑,对于串S,根据next[strlen(S)-1]得到的最长相同前后缀为S1,则再根据next[strlen(S1)-1]得到的S1的最长相同前后缀S2肯定也为S的相同前后缀。(通过画图可以很容易的证明)。 
    这样,通过不断的向前查找next数组,得到一系列的相同前后缀。下面证明这些前后缀包含了所有的相同前后缀: 
        由于我们得到的是一系列最长相同前后缀,假设有一个相同的前后缀Sk不属于这些通过next递推得到的前后缀集合,那么len(Sk)必定小于len(S1),且Sk必定为S1的子串(通过画图很容易看出来);此时若Sk是S1的最长前后缀,则与前提Sk不为某一子串的最长前后缀矛盾,那么Sk不是S1的最长前后缀,则可以退出len(Sk)必定小于S2,且Sk必定为S2的相同前后缀..... 数学归纳递推下去,可以知道Sk要么为某个Si的最长前后缀,要么len(Sk) = 0. 这样可以证明这些通过next数组递推得到的前后缀包含了所有的相同前后缀

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;int Next[400005];
char str[400005];
int ans[400005];
int cnt;
int len;void getNext()
{Next[0] = -1;int i = 0, j = -1;while (i < len){if (j == -1 || str[i] == str[j]){++i;++j;Next[i] = j;}else j = Next[j];}
}int main()
{while (scanf("%s", str) != EOF){len = strlen(str);getNext();cnt = 0;int t = Next[len - 1];while (t != -1){if (str[t] == str[len - 1]) ans[cnt++] = t + 1;t = Next[t];}for (int i = cnt - 1; i >= 0; --i){printf("%d ", ans[i]);}printf("%d\n", len);}return 0;
}

kmp2-HDU1358 HUST1010 POJ2406 POJ2752相关推荐

  1. 【KMP】重复子串(ybtoj KMP-2)

    正题 ybtoj KMP-2 题目大意 问你一个字符串最多由多少个相同的字符串组合而成 解题思路 如下图,先用KMP求出nx数组,那么有1∼nxn1\sim nx_n1∼nxn​和(n−nxn)∼n( ...

  2. [poj2752]Seek the Name, Seek the Fame_KMP

    Seek the Name, Seek the Fame poj-2752 题目大意:给出一个字符串p,求所有既是p的前缀又是p的后缀的所有字符串长度,由小到大输出. 注释:$1\le strlen( ...

  3. poj2752 字符串子KMP应用

    统计前缀后缀相等的个数,包括自身,从小到大输出.可以通过next[]向前统计.因为每一个next[i]都指向该串前部字串(p0p1..pk-1)与i之前字串相等(pi-k+1...pi-2pi-1)的 ...

  4. POJ2406简单KMP

    题意:      给一个字符串,求最大的前缀循环周期,就是最小的循环节对应的最大的那个周期. 思路:      KMP的简单应用,求完next数组后有这样的应用:next[i] :是最大循环节的第几位 ...

  5. POJ2406 KMP前缀周期

    题意:       给你一个字符串,长度小于1百万,问你他最多可以拆成集合相同字符串,例如abcabcabc 可以拆成3个abc,所以输出3. 思路:       这个是比较常规的next应用,首先假 ...

  6. hdu1358 最小循环节,最大循环次数 KMP

    题意:       给你一个字符串,让你找到一些字符串,这个字符串是从第一个字母开始的,并且他可以分成1个一上循环子结构够成的,比如 abcabcabc  那么当前的这个串就是三个abc构成的,他的A ...

  7. poj-2406(kmp水题)

    题意:定义一个a*b=字符串a连接字符串b:给你一个字符串s,问你这个字符串最多能用多少个字符串t连接得到:例如:aaaa=4个a构成: 解题思路:kmp水题,next数组除了查找字串以外最广泛的一种 ...

  8. poj-2752 Seek the Name, Seek the Fame **

    /* * KMP **/ #include <cstdio>#include <cstring>using namespace std; const int maxL = 40 ...

  9. poj2406 Power Strings

    这题只是简单的KMP 算法. 只是有一点需要注意的就是当最后一个的大小是 len % (len - next[len])不够除的时候, 要直接判断是1, 不用继续计算.其他的就是裸的求next Vie ...

最新文章

  1. 高度平衡二叉树的构建_平衡二叉树(AVL)树
  2. 【Android工具】更新WPS全功能正版授权无广告版
  3. 新产品孕育记:PM如何把一款产品从0带到1
  4. bash: gitbook: command not found
  5. C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)
  6. javascript 本地对象和内置对象_详解 JavaScript 面向对象
  7. Android wpa_supplicant 四次握手 流程分析
  8. php1到5000排序,常用的排序算法(一)--快速排序(PHP实现)
  9. Spring Boot 集成 WebSocket,轻松实现信息推送!
  10. 《C》C语言编程实现指定阶“m序列”并通过gnuplot绘图
  11. Racket 的诞生与发展
  12. 详解网站建设方案流程
  13. golang连接FTP服务器并下载
  14. pytorch学习第三天: 阿里云物联网平台使用
  15. 第一类与第二类曲面积分的关系与变换
  16. 高级数据结构之R树(R-tree)
  17. 关于Excel不能多开多个窗口的问题
  18. MySQL查询和删除重复记录
  19. 线性回归(Lasso,Ridge,ElasticNet)调参
  20. 网站敏感骂人词库及算法(附6仟个敏感词)

热门文章

  1. 限定概率抽奖_守护星已点亮,内测皮肤得到没?从天美抽奖概率分析:地址什么梗...
  2. C++ Lambda表达式基本用法
  3. WSAGetLastError
  4. 设备I/O之OVERLAPPED
  5. LSGO软件技术团队2015~2016学年第七周(1012~1018)总结
  6. 【转】掌握Azure订阅的关键概念和术语
  7. “菜”鸟理解.NET Framework(CLI,CLS,CTS,CLR,FCL,BCL)
  8. 37职责链模式(Chain of Responsibility Pattern)
  9. Java 10 常用集合继承关系图
  10. ps海报合成教程_如何利用PS制作海报?详细教程来了!