[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;
}

posted @ 2010-11-15 17:47  Sephiroth.L.  阅读(375)  评论(0编辑  收藏  举报