900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > KMP--君住长江头 我住长江尾 日日思君不见君 共饮长江水

KMP--君住长江头 我住长江尾 日日思君不见君 共饮长江水

时间:2019-01-27 01:58:53

相关推荐

KMP--君住长江头 我住长江尾 日日思君不见君 共饮长江水

POJ 3461:Oulipo

题意:

求出第一个串在第二个串中的出现次数...

分析:

KMP板子题...

代码:

1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 //by NeighThorn 6 using namespace std; 7 //眉眼如初,岁月如故 8 9 const int maxn=1000000+5;10 11 int cas,lens,lenp,nxt[maxn];12 13 char s[maxn],p[maxn];14 15 inline void getnxt(void){16nxt[0]=nxt[1]=0;int k;17for(int i=1;i<lenp;i++){18 k=nxt[i];19 while(k&&p[k+1]!=p[i+1])20 k=nxt[k];21 if(p[k+1]==p[i+1])22 nxt[i+1]=k+1;23 else24 nxt[i+1]=0;25}26 }27 28 inline void kmp(void){29int ans=0,posp=1,poss=1;30while(poss<=lens){31 if(p[posp]==s[poss])32 posp++,poss++;33 else if(posp==1)34 poss++;35 else36 posp=nxt[posp-1]+1;37 if(posp==lenp+1)38 ans++,posp=nxt[posp-1]+1;39}40printf("%d\n",ans);41 }42 43 signed main(void){44scanf("%d",&cas);45while(cas--){46 memset(nxt,0,sizeof(nxt));47 scanf("%s%s",p+1,s+1);48 lenp=strlen(p+1);lens=strlen(s+1);49 getnxt();kmp(); 50}51return 0;52 }//Cap ou pas cap. Pas cap.

POJ 2406:Power Strings

题意:

求出每个串的最短循环节出现次数...

分析:

此题两种解法...然而本质上是一样的...

No.1 Hash

对于一个串其前缀A和后缀B相同并且有重叠,并且len%strlen(str-B)==0,那么str-B一定是循环节...所以我们可以用hash水过...

No.2 next数组...

然而更机智的做法是next数组...

代码:

No.1 Hash

1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #define int long long 6 using namespace std; 7 const int maxn=1000000+5,MOD=100000007; 8 char str[maxn]; 9 int len,ans;10 unsigned int hash[maxn],pow[maxn]; 11 signed main(void){12pow[0]=(long long)1;13for(int i=1;i<maxn;i++)14 pow[i]=(pow[i-1]*30)%MOD;15while(scanf("%s",str+1)&&str[1]!='.'){16 len=strlen(str+1),hash[0]=0,ans=1;17 for(int i=1;i<=len;i++)18 hash[i]=(hash[i-1]*30%MOD+str[i]-'a'+1)%MOD;19 for(int i=1;i<len;i++){20 if(len%(len-i)==0){21 if(hash[i]%MOD==(hash[len]-hash[len-i]*pow[i]%MOD+MOD)%MOD){22 ans=len/(len-i);23 }24 }25 }26 cout<<ans<<endl;27}28return 0;29 }

No.2 next数组

1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 //by NeighThorn 6 using namespace std; 7 //眉眼如初,岁月如故 8 9 const int maxn=1000000+5;10 11 int len,nxt[maxn];12 13 char str[maxn];14 15 inline void getnxt(void){16nxt[0]=nxt[1]=0;int k;17for(int i=1;i<len;i++){18 k=nxt[i];19 while(k&&str[k+1]!=str[i+1])20 k=nxt[k];21 if(str[k+1]==str[i+1])22 nxt[i+1]=k+1;23 else24 nxt[i+1]=0;25}26 }27 28 signed main(void){29while(scanf("%s",str+1)&&str[1]!='.'){30 len=strlen(str+1);getnxt();31 if(len%(len-nxt[len])==0)32 printf("%d\n",len/(len-nxt[len]));33 else34 puts("1");35}36return 0;37 }//Cap ou pas cap. Pas cap.

POJ 2752:Seek the Name, Seek the Fame

题意:

输出所有s的合法前缀,合法前缀的定义为前缀等于后缀...

分析:

不断nxt...

代码:

1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 //by NeighThorn 6 using namespace std; 7 //眉眼如初,岁月如故 8 9 const int maxn=400000+5;10 11 int len,tail,nxt[maxn],stk[maxn];12 13 char str[maxn];14 15 inline void getnxt(void){16nxt[0]=nxt[1]=0;int k;17for(int i=1;i<len;i++){18 k=nxt[i];19 while(k&&str[k+1]!=str[i+1])20 k=nxt[k];21 if(str[k+1]==str[i+1])22 nxt[i+1]=k+1;23 else24 nxt[i+1]=0;25}26 }27 28 signed main(void){29while(scanf("%s",str+1)!=EOF){30 len=strlen(str+1);getnxt();tail=0;stk[++tail]=len;31 while(nxt[len])32 stk[++tail]=nxt[len],len=nxt[len];33 for(int i=tail;i>=1;i--)34 printf("%d ",stk[i]);35 puts("");36}37return 0;38 }//Cap ou pas cap. Pas cap.

POJ 3167:Cow Patterns

题意:

给出两个串,如果a和b匹配当且仅当ab中的每个对应位置的数字rank1和rank2相同,rank1代表当前元素前面小于他的元素个数,rank2代表当前元素前面等于他的元素个数,求出匹配串和模式串的匹配位置(开头位置)

分析:

KMP…裸的KMP…就是计算一下rank就好…

因为数字不会超过25,所以直接暴力求rank就好…

代码:

1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 //by NeighThorn 6 using namespace std; 7 const int maxn=100000+5,maxk=25000+5,maxs=25+5; 8 int n,k,s,a[2][maxn],nxt[maxk],num[2][maxn][maxs],vis[maxk]; 9 inline int rank1(int len,int en,int id){10int st=en-len,ans=0;11for(int i=1;i<a[id][en];i++)12 ans+=num[id][en][i]-num[id][st][i];13return ans;14 }15 inline int rank2(int len,int en,int id){16return num[id][en][a[id][en]]-num[id][en-len][a[id][en]];17 }18 inline void getnext(void){19nxt[0]=nxt[1]=0;int p;20for(int i=1;i<k;i++){21 p=nxt[i];int a=rank1(p+1,p+1,1),b=rank1(p+1,i+1,1),c=rank2(p+1,p+1,1),d=rank2(p+1,i+1,1);22 while(p&&(a!=b||c!=d))23 p=nxt[p],a=rank1(p+1,p+1,1),b=rank1(p+1,i+1,1),c=rank2(p+1,p+1,1),d=rank2(p+1,i+1,1);24 if(rank1(p+1,p+1,1)==rank1(p+1,i+1,1)&&rank2(p+1,p+1,1)==rank2(p+1,i+1,1))25 nxt[i+1]=p+1;26 else27 nxt[i+1]=0;28}29 }30 inline void kmp(void){31int posa=1,posb=1,ans=0,stk[maxn];32while(posa<=n){33 if(rank1(posb,posa,0)==rank1(posb,posb,1)&&rank2(posb,posa,0)==rank2(posb,posb,1))34 posa++,posb++;35 else if(posb==1)36 posa++;37 else38 posb=nxt[posb-1]+1;39 if(posb==k+1)40 stk[++ans]=posa-k,posb=nxt[posb-1]+1;41}42cout<<ans<<endl;43for(int i=1;i<=ans;i++)44 cout<<stk[i]<<endl;45 }46 signed main(void){47scanf("%d%d%d",&n,&k,&s);memset(num,0,sizeof(num));48for(int i=1;i<=n;i++)49 scanf("%d",&a[0][i]),num[0][i][a[0][i]]=1;50memset(vis,0,sizeof(vis));51for(int i=1;i<=n;i++)52 for(int j=1;j<=s;j++)53 num[0][i][j]+=num[0][i-1][j];54for(int i=1;i<=k;i++)55 scanf("%d",&a[1][i]),num[1][i][a[1][i]]=1;56for(int i=1;i<=k;i++)57 for(int j=1;j<=s;j++)58 num[1][i][j]+=num[1][i-1][j];59getnext();kmp();60return 0;61 }

By NeighThorn

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。