POJ 3461 Oulipo(字符串匹配,KMP算法)

题意:给出几组数据,每组有字符串W和T,问你W在T中出现几次。

思路:字符串长度很大,用KMP算法。

  一开始写的是:调用KMP算法查找W在T中是否匹配,若匹配,则个数+1。则接下来T的索引移动相应的距离,再调用函数判断T接下来的序列中是否存在W。

         如果不能匹配,则终止。

  结果,这样超时了。。。估计是调用函数上面花费了些时间。

  后来直接在函数中记录出现的个数,这样就不超时了。

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;
const int maxT=1000010;
const int maxW=10010;
char w[maxW],t[maxT];
int suffix[maxW];//suffix[i]=k:表示P中前i个字符中,后缀与前缀间的最长匹配子串的长度。

void dealSuffix(int m){
    memset(suffix,0,sizeof(suffix));
    suffix[0]=-1;
    suffix[1]=0;
    int k=0;
    for(int i=2;i<=m;i++){
        while(k>=0 && w[k]!=w[i-1])
            k=suffix[k];
        suffix[i]=++k;
    }
}

//m为W字符串的长度
int match(int n,int m){
    int i=0,j=0;  //i为T中字符的下标,j为W中字符的下标
    int cnt=0;   //统计W字符串在T字符串中出现的次数
    while(i<=n-1){
        if(j<0){
            i++;
            j=0;
        }
        if(t[i]==w[j]){
            i++;
            j++;
        }
        else if(j>=0){
            j=suffix[j]; //当j=0的时候,suffix[0]=-1,这样j就会小于0,所以一开始有判断j是否小于0
        }

        //W在T中找到匹配
        if(j==m){
            cnt++;
            j=suffix[j];
        }
    }
    return cnt;
}
int main()
{
    int n,lw,lt;
    scanf("%d",&n);
    getchar(); //用gets的话,这里要写个getchar()
    while(n--){
        gets(w);
        gets(t);
        lw=strlen(w);  //W字符串的长度
        lt=strlen(t);  //T字符串的长度
        dealSuffix(lw);
        int ans=match(lt,lw);
        printf("%d
",ans);
    }

    return 0;
}

下面是照搬算法导论上的代码:

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;
const int maxT=1000010;
const int maxW=10010;
char w[maxW],t[maxT];
int suffix[maxW];//suffix[i]=k:表示P中前i个字符中,后缀与前缀间的最长匹配子串的长度。

//m为w字符串的长度
void getSuffix(int m){
    memset(suffix,0,sizeof(suffix));
    suffix[1]=0;
    int k=0;
    for(int i=2;i<=m;i++){
        while(k>0 && w[k]!=w[i-1])
            k=suffix[k];
        if(w[k]==w[i-1])
            k++;
        suffix[i]=k;
    }
}
//n为t字符串的长度,m为W字符串的长度
int match(int n,int m){
    int k=0,ans=0;
    for(int i=0;i<n;i++){
        while(k>0 && w[k]!=t[i])
            k=suffix[k];
        if(w[k]==t[i])
            k++;
        if(k==m){
            ans++;
            k=suffix[k];
        }
    }
    return ans;
}
int main()
{
    int n,lw,lt;
    scanf("%d",&n);
    getchar(); //用gets的话,这里要写个getchar()
    while(n--){
        gets(w);
        gets(t);
        lw=strlen(w);  //W字符串的长度
        lt=strlen(t);  //T字符串的长度
        getSuffix(lw);
        int ans=match(lt,lw);
        printf("%d
",ans);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/chenxiwenruo/p/3335741.html