zoukankan      html  css  js  c++  java
  • 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){
    16     nxt[0]=nxt[1]=0;int k;
    17     for(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         else
    24             nxt[i+1]=0;
    25     }
    26 }
    27 
    28 inline void kmp(void){
    29     int ans=0,posp=1,poss=1;
    30     while(poss<=lens){
    31         if(p[posp]==s[poss])
    32             posp++,poss++;
    33         else if(posp==1)
    34             poss++;
    35         else
    36             posp=nxt[posp-1]+1;
    37         if(posp==lenp+1)
    38             ans++,posp=nxt[posp-1]+1;
    39     }
    40     printf("%d
    ",ans);
    41 }
    42 
    43 signed main(void){
    44     scanf("%d",&cas);
    45     while(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     }
    51     return 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){
    12     pow[0]=(long long)1;
    13     for(int i=1;i<maxn;i++)
    14         pow[i]=(pow[i-1]*30)%MOD;
    15     while(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     }
    28     return 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){
    16     nxt[0]=nxt[1]=0;int k;
    17     for(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         else
    24             nxt[i+1]=0;
    25     }
    26 }
    27 
    28 signed main(void){
    29     while(scanf("%s",str+1)&&str[1]!='.'){
    30         len=strlen(str+1);getnxt();
    31         if(len%(len-nxt[len])==0)
    32             printf("%d
    ",len/(len-nxt[len]));
    33         else
    34             puts("1");
    35     }
    36     return 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){
    16     nxt[0]=nxt[1]=0;int k;
    17     for(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         else
    24             nxt[i+1]=0;
    25     }
    26 }
    27 
    28 signed main(void){
    29     while(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     }
    37     return 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){
    10     int st=en-len,ans=0;
    11     for(int i=1;i<a[id][en];i++)
    12         ans+=num[id][en][i]-num[id][st][i];
    13     return ans;
    14 }
    15 inline int rank2(int len,int en,int id){
    16     return num[id][en][a[id][en]]-num[id][en-len][a[id][en]];
    17 }
    18 inline void getnext(void){
    19     nxt[0]=nxt[1]=0;int p;
    20     for(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         else
    27             nxt[i+1]=0;
    28     }
    29 }
    30 inline void kmp(void){
    31     int posa=1,posb=1,ans=0,stk[maxn];
    32     while(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         else
    38             posb=nxt[posb-1]+1;
    39         if(posb==k+1)
    40             stk[++ans]=posa-k,posb=nxt[posb-1]+1;
    41     }
    42     cout<<ans<<endl;
    43     for(int i=1;i<=ans;i++)
    44         cout<<stk[i]<<endl;
    45 }
    46 signed main(void){
    47     scanf("%d%d%d",&n,&k,&s);memset(num,0,sizeof(num));
    48     for(int i=1;i<=n;i++)
    49         scanf("%d",&a[0][i]),num[0][i][a[0][i]]=1;
    50     memset(vis,0,sizeof(vis));
    51     for(int i=1;i<=n;i++)
    52         for(int j=1;j<=s;j++)
    53             num[0][i][j]+=num[0][i-1][j];
    54     for(int i=1;i<=k;i++)
    55         scanf("%d",&a[1][i]),num[1][i][a[1][i]]=1;
    56     for(int i=1;i<=k;i++)
    57         for(int j=1;j<=s;j++)
    58             num[1][i][j]+=num[1][i-1][j];
    59     getnext();kmp();
    60     return 0;
    61 }

    By NeighThorn

  • 相关阅读:
    Dubbo源码解析(四)之provider暴露篇
    Dubbo源码解析(六)之provider调用篇
    Dubbo源码解析(九)之consumer调用篇
    Dubbo源码解析(八)之consumer关联provider
    Dubbo源码解析(七)之consumer初始化
    Dubbo源码解析(一)之配置解析篇
    MXNet转Onnx出现错误AttributeError: No conversion function registered for op type SoftmaxActivation yet. AttributeError: No conversion function registered for op type UpSampling yet.
    druid和druid-spring-boot-starter 的区别
    AOP@Before,@After,@AfterReturning,@AfterThrowing执行顺序
    NSInvocation
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6270214.html
Copyright © 2011-2022 走看看