zoukankan      html  css  js  c++  java
  • Another Meaning (KMP + DP)

    先用KMP重叠匹配求出各个匹配成功的尾串位置。然后利用DP去求,那转移方程应该是等于

      上一个状态                                        (无法匹配新尾巴)

      上一个状态 + 以本次匹配起点为结尾的状态(就是说有了新的位置) + 1 (单单一个新串)       (匹配成功)

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5 + 7;
    const int mod = 1000000007;
    long long dp[maxn];
    char str1[maxn], str2[maxn];
    bool flag[maxn];
    /*
    * nex[] 的含义:x[i-nex[i]...i-1]=x[0...nex[i]-1]
    * nex[i] 为满足 x[i-z...i-1]=x[0...z-1] 的最大 z 值(就是 x 的自身匹配)
    */
    void kmp_pre(char x[], int m, int kmpNext[]) {
        int i, j;
        j = kmpNext[0] = - 1;
        i = 0;
        while(i < m) {
            while( - 1 != j && x[i] != x[j])
                j = kmpNext[j];
            kmpNext[++i] = ++j;
        }
    }
    /*
    * kmpNext[i] 的意思:nex'[i]=nex[nex[...[nex[i]]]](直到
    nex'[i]<0 或者 x[nex'[i]]!=x[i])
    * 这样的预处理可以快一些
    */
    void preKMP(char x[], int m, int kmpNext[]) {
        int i, j;
        j = kmpNext[0] = - 1;
        i = 0;
        while(i < m) {
            while( - 1 != j && x[i] != x[j])
                j = kmpNext[j];
            if(x[++i] == x[++j])
                kmpNext[i] = kmpNext[j];
            else
                kmpNext[i] = j;
        }
    }
    /*
    * 返回 x 在 y 中出现的次数,可以重叠
    */
    int nex[10010];
    int KMP_Count(char x[], int m, char y[], int n) { //x 是模式串,y 是主串
        int i, j;
        int ans = 0;
    //preKMP(x,m,nex);
        kmp_pre(x, m, nex);
        i = j = 0;
        while(i < n) {
            while( - 1 != j && y[i] != x[j])
                j = nex[j];
            i++;
            j++;
            if(j >= m) {
                ans++;
                flag[i] = 1;
                j = nex[j];
            }
        }
        return ans;
    }
    int main() {
        int T, ncase = 1;
        scanf("%d", &T);
        while(T --) {
            scanf("%s%s", str1, str2);
            int l1 = strlen(str1);
            int l2 = strlen(str2);
            memset(flag, 0, sizeof(flag));
            memset(dp, 0, sizeof(dp));
            KMP_Count(str2, l2, str1, l1);
            for(int i = l2; i <= l1; i ++)
                dp[i] = flag[i] ? (dp[i - 1] + dp[i - l2] + 1) % mod : dp[i - 1];
            printf("Case #%d: %lld
    ",ncase++,(dp[l1] + 1)%mod);
        }
        return 0;
    }
    more crazy more get!
  • 相关阅读:
    string类型版本号比较
    地图
    使用libcurl显示下载进度
    欧几里德&扩展以及求解线性方程学习总结--附上poj1061解题报告
    [置顶] 两台一级域名相同二级域名不同的服务器,怎么共享session
    [源码分享] HIVE表数据量统计&邮件
    Domino 迁移到Exchange 服务器 之在Domino Server 创建用户!
    Lotus 迁移到Exchange POC 之 新建2007 服务器!
    uva 10056
    Lotus 迁移到Exchange 2010 POC 之在Exchange 2007安装Transport Suite!
  • 原文地址:https://www.cnblogs.com/wethura/p/9832388.html
Copyright © 2011-2022 走看看