HDU 6068 Classic Quotation(2017 Multi-University Training Contest 4)

5 篇文章 0 订阅
1 篇文章 0 订阅

题目链接Classic Quotation
题意:给定两个字符串S和T,然后给出k个询问,每次询问输入L,R,输出S的1,ij,n拼接成的字符串中出现字符串T的期望次数。
题解:记A_i表示字符串S的[1,i]能匹配多少个T, prei=ij=1Ai ,B_(i,j)表示T匹配完S中[1,i]的字符后kmp指针指向的位置。 cnti,j=ik=1Bk,j 。C_{i,j}表示kmp指针指向j时从S[i]处匹配能匹配到多少个T, sufi,j=nk=iCk,j 。那么

ANS=L(nR+1)1Li=1L(Ai+j=0T.length+1(cnti,j1nR+1k=RnCk,j))
             =(nR+1)preL+T.length+1j=0(cntj,isufj,R)

#include <bits/stdc++.h>

using namespace std;

const int N = 50005;
char s[N],t[105];
int pre[N],cnt[N][105],suf[N][105],nxt[105];

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n,m,k,l,r;
        scanf("%d %d %d",&n,&m,&k);
        scanf(" %s %s",s+1,t+1);
        int i=0,j=1;
        nxt[1]=0;
        while(j<=m)
            if(!i||t[i]==t[j])
                nxt[++j]=++i;
            else
                i=nxt[i];
        i=j=1;
        memset(cnt,0,sizeof cnt);
        memset(pre,0,sizeof pre);
        memset(suf,0,sizeof suf);
        while(j<=n)
            if(!i||t[i]==s[j]){
                i++;
                j++;
                cnt[j-1][i]++;
                if(i==m+1)
                    pre[j-1]++;
            }else
                i=nxt[i];
        for(int i=1;i<=n;i++){
            pre[i]+=pre[i-1];
            for(int j=0;j<=m+1;j++)
                cnt[i][j]+=cnt[i-1][j];
        }
        for(int i=1;i<=n;i++)
            pre[i]+=pre[i-1];
        for(int p=n;p>=1;p--)
            for(int q=0;q<=m+1;q++){
                int l=p,r=q;
                for(;;)
                    if(!r||s[l]==t[r]){
                        l++;
                        r++;
                        break;
                    }else
                        r=nxt[r];
                suf[p][q]+=suf[l][r]+(r==m+1?1:0);
            }
        for(int i=n-1;i>=1;i--)
            for(int j=0;j<=m+1;j++)
                suf[i][j]+=suf[i+1][j];
        while(k--){
            scanf("%d %d",&l,&r);
            long long ans=1LL*(n-r+1)*pre[l];
            for(int i=0;i<=m+1;i++)
                ans+=1LL*cnt[l][i]*suf[r][i];
            printf("%lld\n",ans);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值