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);
        }
    }
  • 相关阅读:
    网址
    123
    工具安装
    博客专栏-计算机网络
    JQuery(1)
    HTML常用标签
    Spring的线程池技术:ThreadPoolTaskExecutor
    Error:java: 程序包lombok不存在- IDEA+maven+lombok
    Andriod Studio中新创建的xml布局文件无法在R.layout中调用
    SAST : Single-Shot Arbitrarily-Shaped Text Detector论文阅读笔记
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10274670.html
Copyright © 2011-2022 走看看