[KMP]poj 3461:Oulipo

大致题意:
    给出两个字符串,求出模式串pat在母串text中出现了多少次。

 

大致思路:

    基础的KMP算法,要理解KMP的实现原理。(http://bbezxcy.iteye.com/blog/1355293  kmp算法详解)

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int nMax=10005;
const int mMax=1000005;
char text[mMax],pat[nMax];
int lent,lenp,next[nMax];

void get_next(){
    int i,j=-1;
    next[0]=-1;
    for(i=1;i<=lenp;i++){     //pat[j]是不是可以理解为i的前一个字符的next值所指想的字符
        while(j>-1&&pat[j+1]!=pat[i])j=next[j];
        if(pat[j+1]==pat[i])j++;
        next[i]=j;
    }
}

int KMP(){
    int ans=0,i=0,j=-1;
    get_next();
    for(i=0;i<lent;i++){
        while(j!=-1&&pat[j+1]!=text[i]){
            j=next[j];
        }
        if(pat[j+1]==text[i])j=j+1;
        if(j==lenp-1)ans++;  //找到一个匹配
    }
    return ans;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%s%s",pat,text);
        lenp=strlen(pat);
        lent=strlen(text);
        printf("%d\n",KMP());
    }
    return 0;
}

 

    本来打算用刚学的shift_and算法AC,却被狂wa。仔细思考后才明白,shift-and算法需要通过位运算来实现模式的匹配,对于每个字符都用一个长度等于该字符串长度的二进制数来记录模式串中这个字符的活动状态,所以模式串的长度不能超过int的32位,这里pos的长度最长可以达到10^4,显然不可以。先把wa的代码贴上来,留着模版说不好以后还能用上~~

#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int b[200];
char text[1000005];
char pat[10005];
void shiftAnd(){
     int ans=0;
     int lenP = strlen(pat);
     int lenT=strlen(text);
     memset(b,0,sizeof(b));
     for(int i=0;i<lenP;++i){
         b[pat[i]]|=1<<i;
     }
     int status = 0;
     for(int i = 0;i<lenT; ++i){
         status=((status<<1)|1)&b[text[i]];
         if(status&(1<<(lenP -1))){
             ans++;
         }
     }
     printf("%d\n",ans);
 }
int main(){
     int cas;
     cin>>cas;
     while(cas--){
         scanf("%s%s",pat,text);
         shiftAnd();
     }
     return 0;
 }
 

 

你可能感兴趣的:(字符串,KMP,poj 3461,Oulipo)