HDU 2087 题目大意:略
思路:
剪花步条的话.
其实就是匹配完成之后,令j=1的话就可以了,(注意我的next数组不同于一般人的,我的next[1]=0的)这样就是实现在下一个位置继续匹配
AC Program:
#include <vector> #include <list> #include <map> #include <set> #include <queue> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <ctime> #include <queue> #include <cassert> typedef long long ll; #define clr(a) memset((a),0,sizeof (a)) #define rep(i,a,b) for(int i=(a);i<(int)(b);i++) #define per(i,a,b) for(int i=((a)-1);i>=(int)(b);i--) #define inf (0x7fffffff) #define eps 1e-6 #define MAXN #define MODN (1000000007) using namespace std; int next[1000]; char s[1000],t[1000]; int num; void get_next() { int len1=strlen(t+1);//求长度的时候是这么求的 int j=1; int k=0; next[1]=0; while(j<=len1) { if(k==0 || t[j]==t[k])//k跟书本的k的定义其实差不多 { j++; k++; next[j]=k; } else { k=next[k]; } } } void kmp() { int len1=strlen(s+1); int len2=strlen(t+1); int j=1; int i=1; for(;i<=len1&&j<=len2;)//如果是以逗号分开则是或的关系 { if(s[i]==t[j]) { i++; j++; if(j>len2) { j=1; num++; } } else { j=next[j]; if(j==0) { i++; j++; } } } } int main(){ while(cin>>s+1){ if(s[1]=='#') break; cin>>t+1; get_next(); num=0; kmp(); cout<<num<<endl; }; //system("pause"); return 0; }
HDU 1686 题目大意:问模式串能在母串中最多匹配多少次,包括重叠的情况
思路:
其实用得还是基本的next数组定义:当前匹配完了之后,那么假定在下一个位置失配就可以了.
比如:
AZA
AZAZAZA
为什么呢?为什么不是假定在AZA后面ZA这两个之中的其中一个来进行假定失配呢?
因为这就是next[n+1]的意思.他表示整个串的前缀和后缀的最大相等程度.
如果说n+1这个地方失配了,那么next[n+1]会使得AZA根据自己和自己比较得来的前缀后缀相等程度移动相应的步数来匹配原串.
AZAZAZA
* * *
AC Program:
#include <vector> #include <list> #include <map> #include <set> #include <queue> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <ctime> #include <queue> #include <cassert> typedef long long ll; #define clr(a) memset((a),0,sizeof (a)) #define rep(i,a,b) for(int i=(a);i<(int)(b);i++) #define per(i,a,b) for(int i=((a)-1);i>=(int)(b);i--) #define inf (0x7fffffff) #define eps 1e-6 #define MAXN #define MODN (1000000007) using namespace std; int next[100005]; char s[1000005],t[10005]; int num; void get_next() { int len1=strlen(t+1);//求长度的时候是这么求的 int j=1; int k=0; next[1]=0; while(j<=len1) { if(k==0 || t[j]==t[k])//k跟青书上的k的定义类似 { j++; k++; next[j]=k; } else { k=next[k]; } } } void kmp() { int len1=strlen(s+1); int len2=strlen(t+1); int j=1; int i=1; for(;i<=len1&&j<=len2;)//如果是以逗号分开则是或的关系 { if(s[i]==t[j]) { i++; j++; if(j==len2+1) { j=next[j];//哈哈哈哈,终于明白,其实还是最基本的KMP,只不过利用查找子串中 //的最后一个next数组的值而已 num++; } } else { j=next[j];//next[n]是能够求得以n+1为失配位置n长度字符串的前缀后缀的最大相等的值的数组, //但是平常查找子串的时候最多用了n的为失配位置,n-1长度字符串的前缀后缀最大相等的值的数组 } if(j==0)//等于0的时候就是第一个位置失配了,这样就得整体移动1个单位 { i++; j++; } } } int main(){ int test; //cin>>test; scanf("%d",&test); while(test--){ //cin>>t+1>>s+1; scanf("%s%s",t+1,s+1); //想吐血,一开始cin超时到恶心 get_next(); /* for(int i=1;i<=3;i++) cout<<" "<<next[i]; cout<<endl; */ num=0; kmp(); cout<<num<<endl; }; //system("pause"); return 0; }