KMP(一)(简单题)
2016-07-27 13:13
127 查看
<span style="font-size:18px;">/************************************ KMP最初的代码(写next可能会CE) 1.getnext()递推 规定next[0]=-1; 当nextn[j]=k时: 若p[k]==p[j],可以看出next[j+1]=k+1 否则k=next[k] 2.KMP() 当比较到s[i]!=p[j]时,j=nextn[j], 省去了原串的回溯,复杂度O(m+n) 3.对nextn的理解 a.指针j要回溯的位置 b.有多长的前缀重复出现 **************************************/ void getnext() { int j=0,k=-1; nextn[0]=-1; while(j<lenp-1) { if(k==-1 || p[k]==p[j]) { j++; k++; nextn[j]=k; } else k=nextn[k]; } } void KMP() { int i=0,j=0; while(i<lens) { if(j==-1 || s[i]==p[j]) { i++; j++; } else j=nextn[j]; } }</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">/***************************************************************** 题目链接http://acm.hust.edu.cn/vjudge/contest/123950#problem/A KMP统计子串出现次数 ******************************************************************/ #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=10005,inf=1000005; int next[maxn],cnt,lens,lenp; char p[maxn],s[inf]; void getnext() { int j=0,k=-1; next[0]=-1; while(j<lenp-1) { if(k==-1 || p[k]==p[j]) { j++; k++; next[j]=k; } else k=next[k]; } } void KMP() { int i=0,j=0; while(i<lens) { if(j==-1 || s[i]==p[j]) { i++; j++; } else j=next[j]; if(j==lenp)//若成功,只移动j { cnt++; j=next[j-1]; i--; } } }</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">//上题hash解法,时间是KMP的两倍 </span><pre name="code" class="cpp">#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef unsigned long long ll; const int maxs=1000005,maxp=10005; char s[maxs],p[maxp]; int lens,lenp; const ll b=100000007; int cnt() { int i,ans=0; ll t=1,sh=0,ph=0; for(i=0;i<lenp;i++) { t*=b; sh=sh*b+s[i]; ph=ph*b+p[i]; } for(i=0;i+lenp<=lens;i++) { if(sh==ph) ans++; if(i+lenp<lens) { sh=sh*b-s[i]*t+s[i+lenp]; } } return ans; } int main() { int t; scanf("%d",&t); getchar(); while(t--) { gets(p); gets(s); lens=strlen(s); lenp=strlen(p); printf("%d\n",cnt()); } return 0; }</span>下一题题目链接:http://acm.hust.edu.cn/vjudge/contest/123950#problem/B
<span style="font-size:18px;">/**************************** KMP求一个串的重复子串 ****************************/ #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=1000005; char p[maxn]; int lenp,next[maxn]; void getnext() { int j=0,k=-1; next[0]=-1; while(j<lenp) { if(k==-1 || p[k]==p[j]) { j++; k++; next[j]=k; } else k=next[k]; } } int main() { int n,i,kase=1; while(scanf("%d",&n)!=EOF) { if(n==0)break; getchar(); gets(p); lenp=strlen(p); getnext(); printf("Test case #%d\n",kase++); for(i=1;i<=lenp;i++) { if(next[i] && (next[i]%(i-next[i])==0)) { printf("%d %d\n",i,next[i]/(i-next[i])+1); } } printf("\n"); } return 0; } </span>
<span style="font-size:18px;">/******************************************************************* 题目链接:http://acm.hust.edu.cn/vjudge/contest/123950#problem/D KMP找所有前缀出现的次数 相当于每找到一个前缀重复出现都用next数组将 该前缀中包含的每一个前缀都计算一次 ********************************************************************/ #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=200005,mod=10007; char p[maxn]; int lenp,nextn[maxn],cnt; void getnext() { int j=0,k=-1; nextn[0]=-1; while(j<lenp) { if(k==-1 || p[k]==p[j]) { j++; k++; nextn[j]=k; } else k=nextn[k]; } } int main() { int t,i,j; scanf("%d",&t); while(t--) { memset(nextn,0,sizeof(nextn)); scanf("%d",&lenp); getchar(); gets(p); getnext(); cnt=0; for(i=1;i<=lenp;i++) { j=i; while(j) { cnt=(cnt+1)%mod; j=nextn[j]; } } printf("%d\n",cnt); } return 0; }</span>
递归的过程中,当p[j]!=p[k],即不能等于k+1时,令k=next[k],只有这个时候才可能找到最长的,找有没有更小的一个串可以满足。如果找到一个地方的时候next[i]=0说明在这个i之前没有某个串能和整个串的一个前缀匹配,这时候k=next[k]=-1,在返回去加的时候就变成0,说明找不到了,即在j之前没有串能匹配一个前缀。
next[i]=0:说明i之前没有一个串能匹配前缀
next[i]=k:说明有长度为k的前缀可以匹配
next[0]=-1
相关文章推荐
- geoServer 发布geoTiff格式的DEM数据
- IIS和tomcat共用80端口
- tomcat中java.lang.OutOfMemoryError: Java heap space异常处理
- Linux入门笔记——系统目录结构
- 【Redux】数据生命周期
- 从数组中计算出每个数的个数
- S5PV210——内存配置(DDR2)
- 关于javascript中=的返回值
- Android Studio
- client/offset/srooll位置与关系
- 知识积累:CA详解
- 关于javascript中=的返回值
- 解决ActionBar字体设置
- Activity启动另一个Activity的方式总结
- 【redux】Action Reducer Store
- 报错:1130-host ... is not allowed to connect to this MySql server 开放mysql远程连接 不使用localhost
- Oracle 11G在用EXP 导出时,空表不能导出解决
- vs中添加界面皮肤
- Linux命令(19)用户权限管理:chown
- 通过Python使用树莓派的GPIO[未完待续...]