[poj3461]Oulipo_KMP
Oulipo poj-3461
题目大意:给你两个字符串s和p,问s中有多少个等于p的子串。
注释:$1\le strlen(p)\le 10^4\qquad1\le strlen(s)\le 10^6$
想法:刚刚学习KMP,先来一道裸题。什么是KMP?
KMP是一种字符串匹配算法。如果求出在一个母串中子串出现的位置,我们用一种办法就是枚举母串中任意一个位置pos[i]作为子串开始节点,然后向后匹配,如果匹配成功或者失配,我们都必须重新从pos[i]+1开始重新枚举。我们假设已经匹配到了p串的j号字符,但是我们发现p串中的一些字符是不需要进行重新匹配的,我们就可以通过next数组来使得当前的j跳到next[j]来重新进行匹配,这样的算法,就是KMP(3个人名)。
附上版子
这是求next数组的版子
void GetNext() { int pLen=strlen(p); int k=-1; int j=0; next[0]=-1; while(j<pLen) { if(k==-1||p[j]==p[k]) { ++k; ++j; next[j]=k; } else k=next[k]; } }
然后我们一起看一下实现KMP的版子。
void KmpSearch() { int i=0; int j=0; int sLen=strlen(s); int pLen=strlen(p); while(i<sLen) { if(j==-1 || s[i] == p[j] ) i++ , j++; else j=next[j]; if(j==pLen) { ans++,j=next[j]; } } }
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; char p[10010]; char s[1001000]; int next[10010]; void GetNext() { int pLen=strlen(p); int k=-1; int j=0; next[0]=-1; while(j<pLen) { if(k==-1||p[j]==p[k]) { ++k; ++j; next[j]=k; } else k=next[k]; } } int ans=0; void KmpSearch() { int i=0; int j=0; int sLen=strlen(s); int pLen=strlen(p); while(i<sLen) { if(j==-1 || s[i] == p[j] ) i++ , j++; else j=next[j]; if(j==pLen) { ans++,j=next[j]; } } } void original() { memset(next,0,sizeof next); ans=0; } int main() { int cases; scanf("%d",&cases); while(cases--) { original(); scanf("%s%s",p,s); GetNext(); KmpSearch(); printf("%d\n",ans); } return 0; }
小结:第一道KMP(好像大部分KMP的题都被我用hashShi过了)
| 欢迎来原网站坐坐! >原文链接<