最近稍微看了下KMP,不是很懂他们大神的A题姿势,但是模版总该还是要去学的。
其中next数组的求法有两处区别。
第一种:求主串中模式串的个数。HDU2087 剪花布条和HDU4847 Wow! Such Doge!。这两道都比较水可以暴力string::find函数过,
第一个代码:
#include<iostream> #include<algorithm> #include<cstdlib> #include<sstream> #include<cstring> #include<cstdio> #include<string> #include<deque> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; typedef long long LL; int nextval[101010]; void getnext(char s[],int next[]) { int j=0,k=next[0]=-1; int len=strlen(s); while (j<len-1) // { if(k==-1||s[k]==s[j]) { j++; k++; next[j]=next[k]; // } else k=next[k]; } } int sea(char s[],char t[]) { int cnt=0; int i=0,j=0; int la=strlen(s),lb=strlen(t); while (i<la&&j<lb) { if(j==-1||s[i]==t[j]) { i++; j++; } else j=nextval[j]; if(j==lb) { cnt++; j=nextval[j]; } } return cnt; } int main(void) { char a[1010]={0},b[1010]={0}; while (cin>>a) { if(strcmp(a,"#")==0) { break; } cin>>b; memset(nextval,0,sizeof(nextval)); getnext(b,nextval); cout<<sea(a,b)<<endl; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); } return 0; }
后一题代码:
#include<iostream> #include<algorithm> #include<cstdlib> #include<sstream> #include<cstring> #include<cstdio> #include<string> #include<deque> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; typedef long long LL; int nextval[101010]; void getnext(char s[],int nextval[]) { int j=0,k=-1; nextval[0]=-1; int lenp=strlen(s); while(j<lenp-1) // { if(k==-1||s[j]==s[k]) { k++; j++; nextval[j]=nextval[k];// } else k=nextval[k]; } } int sea(char s[],char t[]) { int cnt=0; int i=0,j=0; int la=strlen(s),lb=strlen(t); while (i<la&&j<lb) { if(j==-1||s[i]==t[j]) { i++; j++; } else j=nextval[j]; if(j==lb) { cnt++; j=nextval[j]; } } return cnt; } void change(char a[]) { int len=strlen(a); for (int i=0; i<len; i++) { a[i]=tolower(a[i]); } } int main(void) { char a[1000010]={0},b[]="doge"; getnext("doge",nextval); int cntt=0; while (gets(a)!=NULL) { change(a); cntt+=sea(a,b); memset(a,0,sizeof(a)); } printf("%d\n",cntt); return 0; }
第二种:求子串出现个数,比如abababa aba 要是按第一种求法,这个答案会是2,但出现次数不是个数,因此答案是3。例题为POJ 3461
代码:
#include<iostream> #include<algorithm> #include<cstdlib> #include<sstream> #include<cstring> #include<cstdio> #include<string> #include<deque> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; typedef long long LL; int nextval[101010]; void getnext(char s[],int nextval[]) { int j=0,k=-1; nextval[0]=-1; int lenp=strlen(s); while(j!=lenp) // { if(k==-1||s[j]==s[k]) nextval[++j]=++k; // else k=nextval[k]; } } int sea(char s[],char t[]) { int cnt=0; int i=0,j=0; int la=strlen(s),lb=strlen(t); while (i<la&&j<lb) { if(j==-1||s[i]==t[j]) { i++; j++; } else j=nextval[j]; if(j==lb) { cnt++; j=nextval[j]; } } return cnt; } int main(void) { char a[1000010]={0},b[1000010]={0}; int tcase; scanf("%d",&tcase); while (tcase--) { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(nextval,0,sizeof(nextval)); scanf("%s%s",b,a); getnext(b,nextval); printf("%d\n",sea(a,b)); } return 0; }
至于为什么可以这么玩,让我补完作业再慢慢研究
来源:https://www.cnblogs.com/Blackops/p/5400755.html