zoukankan      html  css  js  c++  java
  • kmp变形 如何判断第i个字符是否匹配函数 hdu 4749

    题目来源:

    http://acm.hdu.edu.cn/showproblem.php?pid=4749

    题意: 

    题意:给出两个数字串A、B。问A中有多少不相交的子串a能匹配B。匹配的意思是a中任意两个位置i和j的大小关系和B的这两个位置的大小关系是一样的。

    思路:若是完全一模一样的匹配的话那么KMP是很好理解的。那么对于上述的比较方式怎么比较两个串相等呢?对于a的位置j和B的位置i(j < i),我们比较aa(1,2 ,...j) 与bb(i - j + 1 , ... , i)这两个串中,j之前aa中小于(或 等于 或 大于)a[j] 的个数, 是否  ==   与  i之前bb中小于(或 等于 或大于) b[i] 的个数  。 

    一个个匹配过去,如果前缀匹配,并且加上当前字母后,前面比这个字母小的,相等的,大于的数字个数都相等,就是匹配 。

    代码如下:

    const int Max_N = 100005 ;
    int sumt[Max_N][26]  , sump[Max_N][26] ; // sum[i][j]表示从第1位到第i位,有sum[i][j] 个j
    int TT[Max_N] , PP[Max_N] , next[Max_N] ;
    int n , m , k ;
    // 每次匹配时 是
    //   (1 ,2 ,... , j)
    // 与(i-j + 1 , ... , i)进行匹配
    bool  ok1(int i, int j){
        int sma1= 0 , equ1 = 0 ,  sma2 = 0 , equ2 = 0 ;
        int h ;
        for(h = 1 ; h <= k ; h++){
            if(h < PP[i])
                sma1 += sump[i][h] - sump[i - j][h] ;
            else if(h == PP[i])
                equ1 += sump[i][h] - sump[i - j][h] ;
            if(h < PP[j])
                sma2 += sump[j][h] ;
            else if(h == PP[j])
                equ2 += sump[j][h] ;
        }
        return (sma1 == sma2) && (equ1 == equ2) ;
    }
    void get_next(){
        int i , k = 0 ;
        next[1] = 0 ;
        for( i = 2 ; i<= m ; i++){
            while(k > 0 && !ok1(i , k + 1))
                k = next[k] ;
            if(ok1(i, k + 1))
                k ++ ;
            next[i] = k ;
        }
    }
    bool ok2(int i , int j){
        int sma1 = 0 , equ1 = 0 ,  sma2 = 0 , equ2 = 0 ;
        int h ;
        for(h = 1 ; h <= k ; h++){
            if(h < TT[i])
                sma1 += sumt[i][h] - sumt[i - j][h] ;
            else if(h == TT[i])
                equ1 += sumt[i][h] - sumt[i - j][h] ;
            if(h < PP[j])
                sma2 += sump[j][h] ;
            else if(h == PP[j])
                equ2 += sump[j][h] ;
        }
        return (sma1 == sma2) && (equ1 == equ2) ;
    }
    int kmp(){
        int i , k = 0 ;
        int cnt = 0 ;
        for(i = 1 ; i<= n ; i++){
            while(k > 0 && !ok2(i , k + 1))
                k = next[k] ;
            if(ok2(i , k + 1))
                k ++ ;
            if(k == m){
                cnt ++ ;
                k = 0 ; // 特殊处理, 字串不相交
            }
        }
        return cnt ;
    }
    int main(){
        while(scanf("%d%d%d" , &n ,&m ,&k) != EOF){
            int i , j ;
            memset(sumt , 0 , sizeof(sumt)) ;
            memset(sump , 0 , sizeof(sump)) ;
            for(i = 1 ; i<= n ; i++){
                 scanf("%d" , &TT[i]) ;
                for(j = 1 ; j<= k ; j++)  sumt[i][j] = sumt[i - 1][j] ;
                    sumt[i][TT[i]] ++ ;
            }
            for(i = 1 ; i<= m ; i++){
                scanf("%d" , &PP[i]) ;
                for(j = 1 ; j <= k ; j++) sump[i][j] = sump[i - 1][j] ;
                sump[i][PP[i]] ++ ;
            }
            get_next() ;
            printf("%d
    " , kmp()) ;
        }
        return 0 ;
    }
  • 相关阅读:
    新autoJS写淘宝福年种福果
    autoJS写淘宝福年种福果
    简七学理财知识
    python一键搭ftp服务器
    域名伪装
    [SWPU2019]Web1
    [网鼎杯 2020 朱雀组]phpweb
    Doc
    Docker简单使用教程
    MySQL数据库基本操作
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3738512.html
Copyright © 2011-2022 走看看