zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    文件上传案例_Socket_测试
    Linux的小整理(入门)
    full stack 第一天
    基础考题 试题
    shell语法
    网络管理
    图像类
    定时储存
    网络管理
    磁盘管理
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3335741.html
Copyright © 2011-2022 走看看