HDU6068 Classic Quotation (KMP)
题目解释
如题
题目分析
首先必定是一个字符串题,那么无非就是字符串的七个算法中的某一个,经过思考后发现是KMP水题。
阅读3min,思考16min,Code18min,Debug9min,总计45min。
代码
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 50010;
char s[maxn], t[maxn], f[maxn];
ll l[maxn][110], r[maxn][110];
void Solve(int n, int m, ll g[][110]){
for(int k = 1; k <= m; k++){
f[1] = f[2] = 1;
for(int i = 2; i <= k; i++){
int j = f[i];
while(j > 1 && t[i] != t[j]) j = f[j];
f[i + 1] = t[i] == t[j] ? j + 1 : 1;
}
for(int i = 1, j = 1; i <= n; i++){
while(j == k + 1 || j > 1 && s[i] != t[j]) j = f[j];
j += s[i] == t[j];
g[i][k] = g[i-1][k] + (j == (k + 1));
}
}
}
int main(){
int T; scanf("%d", &T);
while(T--){
int n, m, q;
scanf("%d%d%d", &n, &m, &q);
scanf("%s%s", s + 1, t + 1);
Solve(n, m, l);
for(int i = 1; i < n - i + 1; i++)
swap(s[i], s[n - i + 1]);
for(int i = 1; i < m - i + 1; i++)
swap(t[i], t[m - i + 1]);
Solve(n, m, r);
for(int i = 1; i < n - i + 1; i++)
for(int j = 1; j <= m; j++)
swap(r[i][j], r[n - i + 1][j]);
for(int i = 2; i <= n; i++)
l[i][m] += l[i - 1][m];
for(int i = n - 1; i > 0; i--)
r[i][m] += r[i + 1][m];
for(int k = 0; k < q; k++){
int L, R;
scanf("%d%d", &L, &R);
ll ans = L * r[R][m] + (n - R + 1) * l[L][m];
for(int j = 1; j < m; j++)
ans += l[L][j] * r[R][m - j];
printf("%lld\n", ans);
}
}
return 0;
}
反思
当字符从s[1]开始保存时要修改fail数组。