zoukankan      html  css  js  c++  java
  • hdu6153 poj3336强化版kmp+线性dp

    发现很早以前用exkmp做过一次,但是对这题来说只要将两个串翻转一下即可转换成s2的所有前缀出现的问题

    /*
    给出s1,s2,求s2的每个后缀在s1中出现的次数
    ans = sum{后缀长度*出现次数} 
    思路:把数组倒过来,求s2的nxt数组 
    
    cnt[i]当匹配到s2的第i位可以对答案做的贡献 
    cnt[i]=当前与s1第i个字符配对的s2的前缀长度+cnt[nxt[j]] 
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define mod 1000000007
    #define maxn 1000005
    #define ll long long
    
    char s1[maxn],s2[maxn];
    int nxt[maxn],m,cnt[maxn],ans; 
    void reserve(char *s){
        int len=strlen(s);
        int i=0,j=len-1;
        while(i<j){
            swap(s[i],s[j]);
            ++i,--j;
        }
    }
    void kmp_pre(char *s){
        memset(nxt,0,sizeof nxt);
        int m=strlen(s);
        int i,j;
        i=0,j=nxt[0]=-1;
        while(i<m){
            while(j!=-1 && s[i]!=s[j]) j=nxt[j];
            nxt[++i]=++j;
        }
        for(int i=1;i<=m;i++)
            cnt[i]=(i+cnt[nxt[i]])%mod;
    }
    void kmp(){
        int n=strlen(s1),m=strlen(s2);
        int i=0,j=0;
        while(i<n){
            while(j!=-1 && s1[i]!=s2[j])
                j=nxt[j];
            ++i,++j;
            ans=(ans+cnt[j])%mod; 
            if(j==m)j=nxt[j];
        }
    } 
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            memset(cnt,0,sizeof cnt);
            scanf("%s%s",s1,s2);
            
            reserve(s1);
            reserve(s2);
            kmp_pre(s2);
            ans=0;
            kmp();
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    Vue(小案例_vue+axios仿手机app)_go实现退回上一个路由
    nyoj 635 Oh, my goddess
    nyoj 587 blockhouses
    nyoj 483 Nightmare
    nyoj 592 spiral grid
    nyoj 927 The partial sum problem
    nyoj 523 亡命逃窜
    nyoj 929 密码宝盒
    nyoj 999 师傅又被妖怪抓走了
    nyoj 293 Sticks
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10274670.html
Copyright © 2011-2022 走看看