码迷,mamicode.com
首页 > 其他好文 > 详细

CODEVS——T 1404 字符串匹配

时间:2017-08-18 22:33:30      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:它的   btn   block   相等   wiki   ima   扩展   script   problem   

 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
题目描述 Description

给你两个串A,B,可以得到从A的任意位开始的子串和B匹配的长度。
给定K个询问,对于每个询问给定一个x,求出匹配长度恰为x的位置有多少个。
N,M,K<=200000

输入描述 Input Description

第一行三个数 N,M,K,表示A的长度、B的长度和询问数。
第二行为串A。
第三行为串B。
接下来K行,每行1个数X。

输出描述 Output Description

对于每个询问输出一个数。

样例输入 Sample Input

6 2 2
aabcde
ab
0
2

样例输出 Sample Output

4
1

数据范围及提示 Data Size & Hint

各个测试点1s

 

exkmp~~~ctrl_c+ctrl_v

    假如有匹配串A长度为N,模式串B长度为M,那么扩展KMP算法可以在O(N+M)的时间内算出对于A的每一个位置,与B的最长匹配长度是多少(即与B串前缀重合的最长长度),算法如下:

        PART_1 初始化next数组

        设next[i]表示B串的i位置开始的字符串与B串的前缀的最长重合长度(注意这里与KMP中的next是不一样的)。明显地,next[1]=M(我的字符串的下标习惯从1开始),next[2]也可以用一个简单的for循环求出,pos初始化为2;当i∈[3,M]时,我首先认为关于1~i-1的信息已全部求出,我们记录一个pos,它的意义是当前已计算出的next数组中,j+next[j]-1能达到的最右端所对应的i,这个不太好理解,可以参考manacher算法的思想戳这(其实manacher和扩展kmp是很像的),令rp=pos+next[pos]-1

        (1)当i+next[i-pos+1]<rp时,易得next[i]=next[i-pos+1]

        (2)当i+next[i-pos+1]>=rp时,rp后的元素,即b[rp+j],可能会和b[rp-i+1+j]相等,这时进行暴力扩展,如果扩展发生,则更新pos为i,next[i]直接在扩展中求出。

        注意:有时rp可能小于i,这时可以加一特判,直接进行暴力求

        PART_2 匹配

        令ans[i]表示a串中以a[i]为开头的后缀和b串的最长匹配长度,设pos表示a串中对于所有的i,i+ans[i]-1能达到的最远位置对应的i,rp就是pos+ans[pos]-1,next[1]暴力求出,pos初始化为1;当i∈[2,N]时:

        (1)若i+next[i-pos+1]-1<rp,则ans[i]=next[i-pos+1]

        (2)若i+next[i-pos+1]-1>=rp,则进行暴力扩展,同时更新pos,ans在扩展时求出

        注意:如果rp<i,那么加一特判,直接暴力扫描

这个题就明了了~~~

 1 #include <algorithm>
 2 #include <cstring>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 
 7 const int N(200000+5);
 8 int n,m,k,lb,la;
 9 int p[N],ans[N];
10 char a[N],b[N];
11 
12 inline void Get_next()
13 {
14     for(int i=2,j=0;i<=lb;p[i++]=j)
15     {
16         for(;b[i]!=b[j+1]&&j>0;) j=p[j];
17         if(b[i]==b[j+1]) j++;
18     }
19 }
20 inline void kmp()
21 {
22     for(int i=1,j=0;i<=la;i++)
23     {
24         for(;a[i]!=b[j+1]&&j>0;) j=p[j];
25         if(a[i]==b[j+1]) j++;
26         ans[j]++;
27     }
28 }
29 
30 int main()
31 {
32     scanf("%d%d%d%s%s",&n,&m,&k,a+1,b+1);
33     la=strlen(a+1); lb=strlen(b+1);
34     Get_next(); kmp();
35     for(int i=lb;i>0;i--) ans[p[i]]+=ans[i];
36     for(int i=0;i<lb;i++) ans[i]-=ans[i+1];
37     for(int pos;k--;)
38     {
39         scanf("%d",&pos);
40         printf("%d\n",ans[pos]);
41     }
42     return 0;
43 }

 

CODEVS——T 1404 字符串匹配

标签:它的   btn   block   相等   wiki   ima   扩展   script   problem   

原文地址:http://www.cnblogs.com/Shy-key/p/7392351.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!