[KMP神马的]STR
【题目描述】
给你两个串A,B,可以得到从A的任意位开始的子串和B匹配的长度。
给定K个询问,对于每个询问给定一个x,求出匹配长度恰为x的位置有多少个。
N,M,K<=200000
【输入格式】
第一行三个数 N,M,K,表示A的长度、B的长度和询问数。
第二行为串A。
第三行为串B。
接下来K行,每行1个数X。
【输出格式】
对于每个询问输出一个数。
【样例输入】
6 2 2
aabcde
ab
0
2
【样例输出】
4
1
【分析】
想法是,用KMP计算出cnt[i]表示可以达到的长度大于等于i的匹配的个数。
那么长度为i的匹配的个数就是cnt[i] – cnt[i + 1]。因为KMP只能求到某个位置的最大匹配。
记a的每个位置的最大匹配长度是x。初始化cnt[i]为i这个最长匹配长度的频率。
如果a[i]所能达到的最大匹配是x,那么以a[i]为结尾长度为ne[x]的字符串也是一个匹配。因为ne[x] <= x。所以要在cnt[ne[x]]上加上cnt[x]。
原题解链接:http://www.tyvj.cn:8080/Problem_Solve.asp?id=1068
#include <stdio.h> #define MAXN 200001 char a[MAXN],b[MAXN]; int ne[MAXN],cnt[MAXN]; int m,n,k,x,t; int main() { freopen("sample.in","r",stdin); freopen("sample.out","w",stdout); scanf("%d%d%d",&n,&m,&t); scanf("%s%s",a,b); for (int i = n;i > 0;--i) a[i] = a[i - 1]; for (int i = m;i > 0;--i) b[i] = b[i - 1]; int k = 0; for (int i = 2;i <= m;++i) { while ((k > 0) && (b[k + 1] != b[i])) k = ne[k]; if (b[k + 1] == b[i]) ++k; ne[i] = k; } k = 0; for (int i = 1;i <= n;++i) { while ((k > 0) && (b[k + 1] != a[i])) k = ne[k]; if (b[k + 1] == a[i]) ++k; ++cnt[k]; } for (int i = n;i > 0;--i) cnt[ne[i]] += cnt[i]; for (int i = 1;i <= t;++i) { scanf("%d",&x); printf("%d\n",cnt[x] - cnt[x + 1]); } return 0; }