KMP总结
来源:互联网 发布:飞行器制造就业数据 编辑:程序博客网 时间:2024/04/27 20:02
当一个字符串以0为起始下标时,next[i]可以描述为"不为自身的最大首尾重复子串长度"。也就是说,从模式串T[0...i-1]的第一个字符开始截取一段长度为m(m < i-1)子串,再截取模式串T[0...i-1]的最后m个字符作为子串,如果这两个子串相等,则该串就是一个首尾重复子串。我们的目的就是要找出这个最大的m值。例如:
若 i = 4 ,则 i - 1 = 3 , m = next[4] = 2
从T[0...3]截取长度为2的子串,为"ab"
从T[0..3]截取最后2个字符,为"ab"
此时2个子串相等,则说明 next[4] = 2成立,也可证明 m = 2为最大的m值。
求模式串在匹配串中出现的次数(可重复计算如aa在aaa中出现2次)。
char word[100008] , text[1000008] ;int next[100008] ;void getnext(char s[]){ int len = strlen(word) ; next[0] = -1 ; int i = 0 , j = -1 ; while(i < len){ if(j == -1 || s[i] == s[j]) next[++i] = ++j ; else j = next[j] ; }}int kmp(){ getnext(word) ; int lword = strlen(word) , ltext = strlen(text) ; int s = 0 , i =0 , j = 0 ; while(i < ltext){ while(i < ltext && j < lword){ if(j == -1 || text[i] == word[j]){ i++ ; j++ ;} else j = next[j] ; if(j == lword){ s++ ; j = next[j] ;//若不能重复计算则j=0 } } } return s ;}
Power Strings
abcd 1aaaa 4
ababab 3
getnext(word) ; int len = strlen(word) ; int x = len - next[len] ; if(len % x == 0) printf("%d\n" , len/x) ; else puts("0") ;
求最少在末尾添加几个字符,使得串成为循环串
getnext(word) ; len = strlen(word) ; minrepeat = len - next[len] ; if(minrepeat == len) printf("%d\n" ,len) ; else if(len % minrepeat == 0) puts("0") ; else printf("%d\n" , minrepeat - len%minrepeat) ;
求前缀的循环周期
示例:abababab前4个字符,循环字串为ab,有2个循环周期 ab|ab
前6个字符,循环字串为ab,有3个循环周期 ab|ab|ab
前8个字符,循环字串为ab,有4个循环周期 ab|ab|ab|ab
输出:
4 2
6 3
8 4
getnext(word) ; for(i = 2 ; i <= len ; i++){ if(i%(i-next[i])==0 && next[i]!=0) printf("%d %d\n" ,i , i/(i-next[i])) ; }
求给定字符串含前缀的数量
abab 前缀为a , ab ,aba,abab ,abab中共有六个子串是前缀a a ab ab aba abab 答案为6
dp[i]:以string[i]结尾的子串总共含前缀的数量
dp[i=dp[next[i]]+1,即以i结尾的子串中含前缀的数量加上前j个字符这一前缀
getnext(word) ; s = dp[0] = 0 ; for(i = 1 ; i <= n ; i++){ dp[i] = dp[next[i]] + 1 ; s = (s + dp[i]) % 10007 ; } printf("%d\n" , s) ;
求最长的a的前缀同时满足是b的后缀
int s1 = strlen(word) ; int s2 = strlen(text) ; strcat(word , text) ; getnext(word) ; int i = s1+s2 ; while(next[i]>0 && (next[i]>s1 || next[i]>s2 )) i = next[i] ; if(next[i]){ word[next[i]] = '\0' ; printf("%s %d\n" , word , next[i]) ; } else puts("0") ;
求既是前缀又是后缀的前缀的可能的长度
getnext(word) ; int i , j = 0 ; ans[++j] = i = strlen(word) ; while(next[i] > 0){ ans[++j] = next[i] ; i = next[i] ; }
最小覆盖矩阵
把一整行的字符当做一个字符,r行字符相当于一个字符串,求最小的循环节得到H
暴力统计W
char word[10008][78] ;int next[10008] ;int n , m ;void getnext(){ next[0] = -1 ; int i = 0 , j = -1 ; while(i < n){ if(j == -1 || strcmp(word[i] , word[j]) == 0) next[++i] = ++j ; else j = next[j] ; }}int dp[78] ;int main(){ int i , x , y ; while(scanf("%d%d" ,&n , &m) != EOF){ for(i = 0 ; i < n ; i++) scanf("%s" , word[i]) ; memset(dp , 0 , sizeof(dp)) ; for(i = 0 ; i < n ; i++){ for(int j = 1 ; j <= m ; j++){ for(x = 0 , y = j ; y < m ; x++ , y++){ if(word[i][x%j] != word[i][y]) break ; } if(y == m) dp[j]++ ; } } for(i = 1 ; i <= m ; i++) if(dp[i] == n) break ; getnext() ; printf("%d\n" , i * (n - next[n])) ; } return 0 ;}
非暴力统计W
char s[78] ;int main(){ int i , x , y ; while(scanf("%d%d" ,&n , &m) != EOF){ for(i = 0 ; i < n ; i++) scanf("%s" , word[i]) ; memset(dp , 0 , sizeof(dp)) ; for(i = 0 ; i < n ; i++){ strcpy(s , word[i]) ; for(int j = m-1 ; j > 0 ; j--){ s[j] = 0 ; for(x = 0 , y = 0 ;word[i][y]; x++ , y++){ if(! s[x]) x = 0 ; if(s[x] != word[i][y]) break ; } if(! word[i][y]) dp[j]++ ; } } for(i = 0 ; i < m ; i++) if(dp[i] == n) break ; getnext() ; printf("%d\n" , i * (n - next[n])) ; } return 0 ;}
0 0
- kmp总结
- KMP总结
- kmp总结
- KMP总结
- KMP总结
- KMP总结
- KMP总结
- KMP (KMP+拓展KMP)算法总结
- KMP算法总结
- kmp算法总结
- Poj KMP 总结
- KMP算法总结
- KMP算法总结
- [暂定]KMP总结
- KMP算法学习总结
- KMP算法大总结
- kmp算法总结
- KMP算法总结
- __builtin_offsetof()
- 某互联网(特大型)公司游戏元数据管理系统前端开发技术
- 微信网页内分享设置
- oprofile的使用
- PHP代码审计学习总结
- KMP总结
- jquery.paginate.js的样式问题
- ASP.NET缓存全解析3:页面局部缓存
- iOS label内容加载不全
- 新人报道
- 13年iOS笔记小结
- Essential WPF电子表格控件Essential Grid for WPF下载及介绍
- 警告:Do not Access Superglobal $_POST Array Directly
- FileSystemObject处理文件