POJ 2406(KMP) 证明
来源:互联网 发布:ubuntu默认字体 编辑:程序博客网 时间:2024/05/16 14:27
KMP的精髓就是next数组是求pattern的某个后缀是其前缀。求法是递推。
len%(len-1-next[len-1]) == 0 则是幂等的串(应该是叫幂等吧?哈哈。自创)
数目就是len/(len-1-next[len-1])
这题我想的证明是分情况,
1.前缀后缀有重叠,那么画个图
abcdefg比如a-e==c-g就是说next[g] = c
那么a=c, b=d,c=e,d=f,e=g
如果len%(len-next[len-1])==0,那么就是说len能整除ab的长度,ab的长度也等于fg的长度。而两者之间的,后缀cg的前半部分c-f=a-d,cd是重合部分,长度相等,那么ab长度等于ef长度。
前缀af的后半部分重叠部分,cf=
2.前缀后缀没重叠,那么必然前后缀相邻,不然没法是幂等的。又因为前后缀相等,所以就幂等了。
KMP的实现,千万不要用网上的常见方法,很坑爹,是错的。
#if 0
void GetNext(char *s, int n)
{
int i = 0;
int j = -1;
next[0] = -1;
while (i < n) {
if (j == -1 || s[i] == s[j]) {
++i;
++j;
next[i] = j;
} else
j = next[j];
}
}
#endif
这种东西你让人怎么理解。比如aaab这个串,求出来next竟然是 next[0] = -1 , next[1] = 0, next[2] = 1, next[3] = 2.
next[3]怎么能等于2呢。这是人家代码实现问题了。这种实现是错误的
算法导论上面的写法
void GetNext(char *s, int n)
{
int i = 0;
int j = -1;
next[0] = -1;
for (i = 1; i < n; i++) {
while(j>=0 && (s[j+1]!=s[i]))
j = next[j];
if (s[j+1] == s[i])
j++;
next[i] = j;
}
}
很好理解next求出来分别是-1,0,1,-1所以我那个公式len%(len-1-next[len-1]) == 0就是对的。
如果用网上的那种,应该是len%(len-next[len]),要用到next数组最后一个元素的后面一个位置才行。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
char s[1000001];
int next[1000001];
#if 0
void GetNext(char *s, int n)
{
int i = 0;
int j = -1;
next[0] = -1;
while (i < n) {
if (j == -1 || s[i] == s[j]) {
++i;
++j;
next[i] = j;
} else
j = next[j];
}
}
#endif
void GetNext(char *s, int n)
{
int i = 0;
int j = -1;
next[0] = -1;
for (i = 1; i < n; i++) {
while(j>=0 && (s[j+1]!=s[i]))
j = next[j];
if (s[j+1] == s[i])
j++;
next[i] = j;
}
}
void Kmp(char *a, char *b, int an, int bm)
{
int i = 0;
int j = -1;
for (i = 0; i < an; i++) {
while (j >= 0 && b[j+1]!=a[i])
j = next[j];
if (b[j+1] == a[i])
j++;
if (j == bm - 1) {
printf("pattern occurs with shift %d\n", i+1-bm);
j = next[j];
}
}
}
int main()
{
while(1) {
//memset(s, 0, sizeof(0)); // scanf will add '\0'
memset(next, 0, sizeof(0));
scanf("%s", s);
char pattern[1024];
scanf("%s", pattern);
if (strcmp(s, ".") == 0) break;
int len = strlen(s);
GetNext(s, len);
#if 1
//if (len == 2 && s[0] != s[1]) // my new GetNext function according CLRS will cover this.
// printf("1\n");
if (len%(len-next[len-1]-1) == 0) {
printf("%d\n", len/(len-next[len-1]-1));
} else
printf("1\n");
#endif
#if 0
if (len%(len-next[len]) == 0)
printf("%d\n", len/(len-next[len]));
else
printf("1\n");
#endif
Kmp(s, pattern, len, strlen(pattern));
}
}
- POJ 2406(KMP) 证明
- poj 2406(kmp)
- POJ-2406(KMP)
- poj 2406 1961 简单证明
- KMP简单证明
- poj 2406:Power Strings(KMP)
- poj 2406 power string(KMP)
- poj 2406 Power Strings(kmp算法)
- POJ 2406 Power Strings(kmp)
- POJ 题目2406 Power Strings(KMP)
- POJ 2406 Power String(KMP)
- POJ 2406 Power Strings(kmp)
- poj 2406 Power Strings (KMp)
- POJ 2406 Power Strings (KMP)
- POJ 2406 Power Strings(KMP)
- poj-2406-Power Strings(KMP)
- poj 2406 Power Strings(kmp)
- poj 2406Power Strings(KMP入门)
- POJ3126 Prime Path
- Eclipse界面中文字体显示过小问题的解决办法
- sqlserver2008不能创建全文索引解决办法
- VI命令简录
- Android 手机截屏
- POJ 2406(KMP) 证明
- 百度地图总结
- 使用perf生成Flame Graph(火焰图)
- 常见HTTP状态汇总
- 何谓 SMART rule?
- android.os.NetworkOnMainThreadException错误笔记
- 华为机试.约瑟夫环
- 深入学习Django源码基础12 - 简要分析Django中template模块2
- java获取的毫秒与c#获取的毫秒相关问题