HDU 6068 Classic Quotation KMP+DP
2017-08-06 10:07
399 查看
Classic Quotation
[align=left][b]Problem Description[/b][/align]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)(1≤i≤L,R≤j≤n) equiprobably? Your task is to find the answer E, and report E×L×(n−R+1) to him.
Note : When counting occurrences, T can overlap with each other.
[align=left][b]Input[/b][/align]
The first line of the input contains an integer C(1≤C≤15), denoting the number of test cases.
In each test case, there are 3 integers n,m,k(1≤n≤50000,1≤m≤100,1≤k≤50000) 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(1≤L<R≤n) in each line, denoting a question.
[align=left][b]Output[/b][/align]
For each question, print a single line containing an integer, denoting the answer.
[align=left][b]Sample Input[/b][/align]
1
8 5 4
iamnotsb
iamsb
4 7
3 7
3 8
2 7
[align=left][b]Sample Output[/b][/align]
1
1
0
0
[b]题意:[/b]
给两个字符串只包含小写字母,长度分别为n,m
k个询问,每次询问给出一个L,R
任意的 ( i , j ) ( 1 ≤ i ≤ L , R ≤ j ≤ n ) 删除S串范围(i+1,j-1)内的字符,求出T串在新串内出现的次数总和
[b]题解:[/b]
我还是照搬官方题解吧
#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 ,ffail ; LL dp [M],f [M],sumdp [M],sumf [M],dp2 [M],f2 [M]; char a ,b ; 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\n",solve(L,R)); } } return 0; }
相关文章推荐
- HDU 6068 Classic Quotation(kmp+dp)
- hdu 3336 Count the string(KMP+dp)
- HDU 3336 Count the string (kmp+dp)
- hdu 3336: Count the string(KMP dp)
- Count the string HDU - 3336 KMP+DP
- hdu 3336 Count the string(KMP+dp)
- hdu-5763 Another Meaning(kmp+dp)
- (HDU)3336 - Count the string 【KMP】+【DP】
- HDU 3336 Count the string(KMP+DP)
- HDU 5763 Another Meaning dp+字符串hash || DP+KMP
- HDU 3689 (KMP+DP || 暴力+dp)
- [kmp+dp] hdu 4628 Pieces
- HDU 3336 Count the string kmp+dp
- HDU 4552 怪盗基德的挑战书 (KMP + DP) 或 后缀数组
- HDU - 5763 Another Meaning(KMP+DP)
- HDU 3336 KMP+DP
- hdu 4552 怪盗基德的挑战书 (kmp+dp)
- 【HDU 3336】Count the string(KMP+DP)
- HDU6068 Classic Quotation KMP+前缀和
- [kmp+dp] hdu 4628 Pieces