2017 Multi-University Training Contest - Team 4 Classic Quotation

Classic Quotation

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)

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
 分析:首先,对于某一对(l,r),我们可以求出答案为preg l + suf r,pref l;
   其中preg表示前缀l中T的个数,pref l表示匹配完前缀l指针所在位置,suf r,pref l表示从r开始的后缀中从pref l指针开始匹配得到的T的个数;
   因为要求所有的贡献和,l<=L,r>=R,所以考虑前缀和与后缀和;
   ans=i=1​~L​​j=R~n​ ​pregi​​ sufj,prefi​​​​=(nR+1)pregL​​+i=0~m1​​ sL,i​​×sufR,i​​
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <cassert>
#include <ctime>
#define rep(i,m,n) for(i=m;i<=(int)n;i++)
#define mod 998244353
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
#define ls rt<<1
#define rs rt<<1|1
#define all(x) x.begin(),x.end()
const int maxn=5e4+10;
const int N=5e4+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
ll qpow(ll p,ll q,ll mo){ll f=1;while(q){if(q&1)f=qmul(f,p,mo)%mo;p=qmul(p,p,mo)%mo;q>>=1;}return f;}
int n,m,k,t,nxt[maxn],nxt1[110][26];
ll pref[maxn],preg[maxn],s[maxn][110],suf[maxn][110];
char a[maxn],b[maxn];
void init(char *a,char *b)
{
    for(int i=0;i<=n;i++)
    {
        pref[i]=preg[i]=0;
        for(int j=0;j<=m;j++)
        {
            s[i][j]=suf[i][j]=0;
        }
    }
    nxt[0]=-1;
    int j=-1;
    for(int i=0;i<=m;i++)
    {
        while(!(j==-1||b[j]==b[i]))j=nxt[j];
        nxt[i+1]=++j;
    }
    j=0;
    for(int i=0;i<n;i++)
    {
        while(!(j==-1||a[i]==b[j]))j=nxt[j];
        if(i)preg[i]=preg[i-1];
        pref[i]=++j;
        s[i][j]++;
        if(j==m)preg[i]++;
    }
    for(int i=1;i<n;i++)
    {
        preg[i]+=preg[i-1];
        for(int j=0;j<=m;j++)
        {
            s[i][j]+=s[i-1][j];
        }
    }
    for(int i=0;i<=m;i++)
    {
        for(int j='a';j<='z';j++)
        {
            int k=i;
            while(!(k==-1||j==b[k]))k=nxt[k];
            nxt1[i][j-'a']=k+1;
        }
    }
    for(int i=n-1;i>=0;i--)
    {
        for(int j=0;j<=m;j++)
        {
            int tmp=nxt1[j][a[i]-'a'];
            suf[i][j]+=suf[i+1][tmp];
            if(tmp==m)suf[i][j]++;
        }
    }
    for(int i=n-1;i>=0;i--)
    {
        for(int j=0;j<=m;j++)
        {
            suf[i][j]+=suf[i+1][j];
        }
    }
}
int main()
{
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        scanf("%s%s",a,b);
        init(a,b);
        while(k--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            ll ret=(n-y+1)*preg[x-1];
            for(int i=0;i<=m;i++)
            {
                ret+=s[x-1][i]*suf[y-1][i];
            }
            printf("%lld\n",ret);
        }
    }
    return 0;
}
posted @ 2017-08-06 16:06  mxzf0213  阅读(223)  评论(0编辑  收藏  举报