zoukankan      html  css  js  c++  java
  • MP and KMP

    MP 是 KMP 的简单版本,目前以下题目都是MP算法

    KMP的原理就不多说了

    http://kb.cnblogs.com/page/176818/

    (这个模板起始的next数组值为0,不是-1,在模板中,next数组叫f数组)

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define maxn XXX//自己定
    char P[maxn] ;
    int f[maxn] ;
    void getFail ( char *P , int *f )//对子串的处理
    {
        int i , j ;
        int m = strlen(P) ;
        f[0] = f[1] = 0 ;
        for( i = 1 ; i < m ; i++ )
        {
            j = f[i] ;
            while( j && P[i] != P[j] )
            {
                j = f[j] ;
            }
            f[i+1] = P[i] == P[j] ? j+1 : 0 ;
        }
    }
    int find( char *T , char *P , int *f )
    {
        int n = strlen( T ) ;
        int m = strlen( P ) ;
        int j , i ;
        getFail( P , f ) ; //预处理匹配串
        for( i = 0 ; i < n ; i++ )
        {
            while( j && P[j] != T[i] )
            {
                j = f[j] ;
            }
            if( P[j] == T[i] ) j++;
            if( j == m ) return i-m;
        }
        return -1 ;//没有匹配到就返回-1
    }
    基本模板

    题目:

    poj3461

    /*
    匹配串<10,000 被匹配串< 1,000,000 最基本的那种
    */
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    #define maxnt 1000009
    #define maxnw 10009
    char w[maxnw];
    char t[maxnt];
    int f[maxnw];
    void getFail(char *p, int *f)
    {
        int i,j;
        f[0] = f[1] = 0;
        int m = strlen(p);
        for(i = 1; i<m; i++){
            j = f[i];
            while(j && p[j] != p[i]) j = f[j];
            f[i+1] = p[j]==p[i]? j+1 : 0;
        }
    }
    int findd()
    {
        int ww = strlen(w);
        int tt = strlen(t);
        int j = 0;
        int ans = 0;
        for(int i=0; i<tt; i++)
        {
            while(j && t[i] != w[j]){
                j = f[j];
            }
            if(t[i] == w[j]){
                j++;
            }
            if(j == ww){
                ans++; j = f[j];
            }
        }
        return ans;
    }
    int main()
    {
        int T;
        scanf("%d%*c", &T);
        while( T-- ){
            scanf("%s",w);
            scanf("%s",t);
            getFail(w,f);
            int result = findd();
            cout <<result<< endl;
        }
        return 0;
    }
    View Code

    poj2406

    /*
     has huge input, use scanf instead of cin to avoid time limit exceed
     will not exceed 1 million characters
     求一个串的最大循环串,输出循环次数
    */
    #define maxn 1001000
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    using namespace std;
    char str[maxn];
    int f[maxn];
    void getFail (char *p, int *f)
    {
        int j,i;
        int m = strlen(p);
        f[0] = f[1] = 0;
        for(i=1; i<m; i++)
        {
            j = f[i];
            while(j && p[i]!=p[j]){
                j = f[j];
            }
            f[i+1] = p[i]==p[j]? j+1:0;
        }
    }
    int main()
    {
        while(scanf("%s", str ) && str[0]!='.')
        {
            getFail(str,f);
            int m = strlen(str);
            //cout<<m<<""<<f[m]<<endl;
            if( m % (m-f[m]) == 0 ){
                printf("%d
    ", m/(m-f[m]));
            }
            else{
                printf("1
    ");
            }
        }
        //cout << "Hello world!" << endl;
        return 0;
    }
    View Code

    poj2752

    /*
    求既是前缀也是后缀的子串长度
    1 <= Length of S <= 400000
    */
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #define maxn 400009
    using namespace std;
    char p[maxn];
    int f[maxn];
    int getans[maxn];
    void getFail(char *p, int *f)
    {
        int i,j;
        f[0] = f[1] = 0;
        int m = strlen(p);
        for(i = 1; i<m; i++){
            j = f[i];
            while(j && p[j] != p[i]) j = f[j];
            f[i+1] = p[j]==p[i]? j+1 : 0;
        }
    }
    int Gett(int*getans, char*p)
    {
        int countt;
        int last = f[strlen(p)];
        countt = 1;
        getans[0] = strlen(p);
        if(last == 0) {
            return countt;
        }
        else{
            while(last){
                getans[countt++] = last;
                last = f[last];
            }
            return countt;
        }
    }
    int main()
    {
        int countt;
        while(~scanf("%s",p)){
            getFail(p,f);
            countt = Gett(getans, p);
            while(countt){
                printf("%d", getans[--countt]);
                if(countt == 0){
                    printf("
    ");
                }
                else{
                    printf(" ");
                }
            }
        }
        return 0;
    }
    View Code

    poj2185

    /**
    最小覆盖子串(串尾多一小段时,用前缀覆盖)长度为n-next[n](n-pre[n]),n为串长。
    论证见这篇博客:http://blog.csdn.net/fjsd155/article/details/6866991
    */
    /*行 <= 10,000 列 <= 75*/
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    
    #define maxnR 10009
    #define maxnC 79
    using namespace std;
    int r,c;
    char sarray[maxnR][maxnC];
    char carray[maxnC][maxnR];
    int fs[maxnR], f[maxnR];
    int gcd(int a_,int b_)
    {/*要判断大小*/
        int a,b;
        if(a_>b_){
            a = a_; b = b_;
        }
        else{
            a = b_; b = a_;
        }
        return b==0?a:gcd(b,a%b);
    }
    int gong(int a,int b)
    {
        return a*b/gcd(a,b);
    }
    void getFail(char *p, int *f)
    {
        int i,j;
        f[0] = f[1] = 0;
        int m = strlen(p);
        for(i = 1; i<m; i++){
            j = f[i];
            while(j && p[j] != p[i]) j = f[j];
            f[i+1] = p[j]==p[i]? j+1 : 0;
        }
    }
    int main()
    {
        while(~scanf("%d%d",&r, &c)){
            for(int i=0; i<r; i++){
                scanf("%s",sarray[i]);
                //printf("--%s
    ",sarray[i]);
                for(int j=0; j<c;j++){
                    carray[j][i] = sarray[i][j];
                }
    
                getFail(sarray[i], f);
                int n = strlen(sarray[i]);
                fs[i] = n - f[n];
            }
            int hang = 1;
            for(int i=0; i<r; i++){
                hang = gong(hang, fs[i]);
            }
            for(int j=0; j<c; j++){
                carray[j][r] = '';
            /*这里出了问题,一开始这句话加在输入行,但是当列比行多,那么我们只保证了r个列串末尾被初始化,不是c个*/
                //printf("--%s
    ",carray[j]);
                getFail(carray[j],f);
                int m = strlen(carray[j]);
                fs[j] = m - f[m];
            }
            int lie = 1;
            for(int j=0; j<c; j++){
                lie = gong(lie,fs[j]);
            }
            if(hang > c){
                hang = c;
            }
            if(lie > r){
                lie = r;
            }
            cout << hang*lie << endl;
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Asp.Net选择TreeView前面的复选框引起回发
    Asp.Net自动发送邮件代码
    Asp.Net类型转换类(通用类)
    Eclipse 快捷键
    结对项目开发之电梯调度问题
    输出文章中几个最高频率单词和次数
    求整数数组中和最大的子数组的和
    Android定位功能(二)
    分布式拒绝服务攻击(DDoS)原理及防范
    定义Profile用户文件详解
  • 原文地址:https://www.cnblogs.com/puluotiya/p/4333916.html
Copyright © 2011-2022 走看看