HDU 6068 Classic Quotation KMP+DP

Classic Quotation

Problem Description
When online chatting, we can save what somebody said to form his ''Classic Quotation''. Little Q does this, too. What's more? He even changes the original words. Formally, we can assume what somebody said as a string S whose length is n. He will choose a continuous substring of S(or choose nothing), and remove it, then merge the remain parts into a complete one without changing order, marked as S. For example, he might remove ''not'' from the string ''I am not SB.'', so that the new string S will be ''I am SB.'', which makes it funnier.



After doing lots of such things, Little Q finds out that string T occurs as a continuous substring of S very often.

Now given strings S and T, Little Q has k questions. Each question is, given L and R, Little Q will remove a substring so that the remain parts are S[1..i] and S[j..n], what is the expected times that T occurs as a continuous substring of S if he choose every possible pair of (i,j)(1iL,Rjn) equiprobably? Your task is to find the answer E, and report E×L×(nR+1) to him.

Note : When counting occurrences, T can overlap with each other.
 
Input
The first line of the input contains an integer C(1C15), denoting the number of test cases.

In each test case, there are 3 integers n,m,k(1n50000,1m100,1k50000) in the first line, denoting the length of S, the length of T and the number of questions.

In the next line, there is a string S consists of n lower-case English letters.

Then in the next line, there is a string T consists of m lower-case English letters.

In the following k lines, there are 2 integers L,R(1L<Rn) in each line, denoting a question.
 
Output
For each question, print a single line containing an integer, denoting the answer.
 
Sample Input
1 8 5 4 iamnotsb iamsb 4 7 3 7 3 8 2 7
 
Sample Output
1 1 0 0
 

题意:

  给两个字符串只包含小写字母,长度分别为n,m

  k个询问,每次询问给出一个L,R

  任意的 ( ≤ ≤ ≤ ≤ ) 删除S串范围(i+1,j-1)内的字符,求出T串在新串内出现的次数总和

题解:

  我还是照搬官方题解吧

  

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
typedef unsigned long long ULL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N = 6e4+10, M = 2e2+20,inf = 2e9;

int zfail[N],ffail[N];
LL dp[N][M],f[N][M],sumdp[N][M],sumf[N][M],dp2[N][M],f2[N][M];
char a[N],b[N];
int n,m,k,T;
LL solve(int ll,int rr) {
    LL ret = 0;
    ret += 1LL * sumdp[ll][m] * (n - rr + 1) + 1LL * sumf[rr][1] * (ll);
    for(int i = 1; i < m; ++i) {
        ret += 1LL*dp2[ll][i] * f2[rr][i+1];
    }
    return ret;
}
void init() {
    for(int j = 0; j <= m+1; ++j) zfail[j] = 0,ffail[j] = m+1;
    for(int i = 0; i <= n+1; ++i)
        for(int j = 0; j <= m+1; ++j)
            dp[i][j] = 0,f[i][j] = 0,sumdp[i][j] = 0,sumf[i][j] = 0;
    int j = 0;
    for(int i = 2; i <= m; ++i) {
        while(j&&b[j+1]!=b[i]) j = zfail[j];
        if(b[j+1] == b[i]) j++;
        zfail[i] = j;
    }
    j = m+1;
    for(int i = m-1; i >= 1; --i) {
        while(j<=m&&b[j-1]!=b[i]) j = ffail[j];
        if(b[j-1] == b[i]) j--;
        ffail[i] = j;
    }
    j = 0;
    for(int i = 1; i <= n; ++i) {
        while(j&&a[i]!=b[j+1]) j = zfail[j];
        if(b[j+1] == a[i]) j++;
        dp[i][j] += 1;
    }
    j = m+1;
    for(int i = n; i >= 1; --i) {
        while(j<=m&&b[j-1]!=a[i]) j = ffail[j];
        if(b[j-1] == a[i]) j--;
        f[i][j] += 1;
    }

    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            dp[i][j] += dp[i-1][j];
            sumdp[i][j] += sumdp[i-1][j]+dp[i][j];
        }
    }
    for(int i = n; i >= 1; --i) {
        for(int j = m; j >= 1; --j) {
            f[i][j] += f[i+1][j];
            sumf[i][j] += sumf[i+1][j]+f[i][j];
        }
    }
}

void init2() {
     for(int i = 0; i <= n+1; ++i)
        for(int j = 0; j <= m+1; ++j)
            dp2[i][j] = 0,f2[i][j] = 0;
    for(int i = 0; i <= n+1; ++i)
        dp2[i][0] = 1,f2[i][m+1] = 1;


    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            if(a[i] == b[j] && dp2[i-1][j-1])
                dp2[i][j] = 1;
        }
    }
     for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
                dp2[i][j] += dp2[i-1][j];
        }
    }
    for(int i = n; i >= 1; --i) {
        for(int j = m; j >= 1; --j) {
            if(a[i] == b[j] && f2[i+1][j+1])
                f2[i][j] = 1;
        }
    }
      for(int i = n; i >= 1; --i) {
        for(int j = m; j >= 1; --j) {
          f2[i][j] += f2[i+1][j];
        }
    }
}

int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d%d%s%s",&n,&m,&k,a+1,b+1);
        init();
        init2();
        while(k--) {
            int L,R;
            scanf("%d%d",&L,&R);
            printf("%lld
",solve(L,R));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zxhl/p/7293968.html