BZOJ 3670 && BZOJ 3620 && BZOJ 3942 KMP

最近感到KMP不会啊,以前都是背板的现在要理解了。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 using namespace std;
 6 const int Maxn=16000;
 7
 8 char S[Maxn];
 9 int k,P[Maxn],Ans;
10
11
12 inline void Kmp(char * Str)
13 {
14     int j=0;
15     for (int i=2;Str[i];i++)
16     {
17         while (Str[j+1]!=Str[i] && j) j=P[j];
18         if (Str[j+1]==Str[i]) j++;
19         P[i]=j;
20     }
21     j=0;
22     for (int i=1;Str[i];i++)
23     {
24         while (Str[j+1]!=Str[i] && j) j=P[j];
25         if (Str[j+1]==Str[i]) j++;
26         while (j<<1>=i) j=P[j];
27         if (j>=k) Ans++;
28     }
29 }
30 int main()
31 {
32     scanf("%s",S+1);
33     scanf("%d",&k);     Ans=0;
34     for (int i=0;S[i+1];i++) Kmp(S+i);
35     printf("%d\n",Ans);
36     return 0;
37 }
38 

BZOJ 3620

其实这就是KMP的P数组的含义,即S[1~P[i]]==S[i-P[i]+1~i],但是题目中要求的的书不能重复,这样就要暴力找一下P[P[i]]就可以完成了。N^2暴力就可以过

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #define LL long long
 6 using namespace std;
 7 const LL Maxn=1000100;
 8 const LL Mod=1000000007;
 9 char S[Maxn];
10 LL k,P[Maxn],Ans,Cnt[Maxn],Kase;
11
12
13 inline void Kmp(char * Str)
14 {
15     LL j=0;
16     Cnt[1]=1;
17     for (LL i=2;Str[i];i++)
18     {
19         while (Str[j+1]!=Str[i] && j) j=P[j];
20         if (Str[j+1]==Str[i]) j++;
21         P[i]=j;
22         Cnt[i]=Cnt[j]+1;
23     }
24
25     j=0; LL Ret;
26     for (LL i=2;Str[i];i++)
27     {
28         while (Str[j+1]!=Str[i] && j) j=P[j];
29         if (Str[j+1]==Str[i]) j++;
30         while (j<<1>i) j=P[j];
31         Ans=(Ans*(Cnt[j]+1))%Mod;
32     }
33 }
34 int main()
35 {
36     scanf("%lld",&Kase);
37     for (LL kase=1;kase<=Kase;kase++)
38     {
39         scanf("%s",S+1);
40         Ans=1; Kmp(S);
41         printf("%lld\n",Ans);
42     }
43     return 0;
44 }
45 

BZOJ 3670

其实和上一道是一样的。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 using namespace std;
 6
 7 const int Maxn=1001000;
 8 char S[Maxn],T[Maxn],Stack[Maxn];
 9 int Lens,Lent,P[Maxn],top,a[Maxn];
10 int main()
11 {
12     scanf("%s",S+1);
13     scanf("%s",T+1);
14     Lens=strlen(S+1),Lent=strlen(T+1);
15     int j=0;
16     for (int i=2;i<=Lent;i++)
17     {
18         while (T[j+1]!=T[i] && j) j=P[j];
19         if (T[j+1]==T[i]) j++;
20         P[i]=j;
21     }
22     j=0;
23     for (int i=1;i<=Lens;i++)
24     {
25         j=a[top]; Stack[++top]=S[i];
26         while (T[j+1]!=Stack[top] && j) j=P[j];
27         if (T[j+1]==Stack[top]) j++;
28         a[top]=j;
29         if (j==Lent) top-=Lent;
30     }
31     for (int i=1;i<=top;i++) putchar(Stack[i]);
32     putchar(‘\n‘);
33     return 0;
34 }
35 

BZOJ 3942

裸的KMP..

时间: 2024-11-10 01:27:34

BZOJ 3670 && BZOJ 3620 && BZOJ 3942 KMP的相关文章

bzoj 3670 动物园 - kmp - 动态规划

Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:“对于一个字符串S,它的长度为L.我们可以在O(L)的时间内,求出一个名为next的数组.有谁预习了next数组的含义吗?” 熊猫:“对于字符串S的前i个字符构成的子串,既是它的后缀又是它的前缀的字符串中(它本身除外),最长的长度记作next[i].

BZOJ 3670 NOI2014 动物园 KMP+dp

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3670 题意概述:令num[i]表示字符串由1~i的字符形成的前缀中不相重叠的相同前后缀的数量,求mul{ num[i] | 1<=i<=L }mod1000000007. 实际上只要对KMP理解的好这就是个水题,可以想到dp求得num数组,num[i]=num[f[i]]+1,f[i]表示字符串的前缀1~i形成的不重叠的最长相同前后缀长度,如果f[i]的话就不存在.题目的提醒实际上很明

BZOJ 3670 NOI2014 动物园 KMP算法

题意: 给定一个长为L的字符串(L<=100W),求一个num数组,num[i]表示长度为i的前缀中字符串S'的数量,其中S'既是该前缀的前缀也是该前缀的后缀,且|S'|*2<=i 求Π(num[i]+1)%1000000007 这就是KMP算法的一个变形...首先求出next数组,顺便求出cnt数组,代表长度为i的前缀经过几次fix=next[fix]会得到0,然后重新匹配一次,这次注意当fix*2>i的时候令fix=next[fix]即可 这题有坑 切忌用num数组代替next 此外

bzoj 3670: [Noi2014]动物园

Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:"对于一个字符串S,它的长度为L.我们可以在O(L)的时间内,求出一个名为next的数组.有谁预习了next数组的含义吗?" 熊猫:"对于字符串S的前i个字符构成的子串,既是它的后缀又是它的前缀的字符串中(它本身除外),最长的长度

BZOJ 1100 POI2007 对称轴osi 计算几何+KMP算法

题目大意:给定一个多边形,求对称轴数量 我X 这究竟是怎么想到KMP的-- 首先 将边字符化 即找到这个多边形的中心 然后用与中心构成的三角形的边-角-边的方式表示这条边 将边顺时针扫一遍 然后倍增至长度为2n-1 再逆时针扫一遍 逆时针扫的那遍在顺时针那遍中出现的次数就是对称轴数目 用KMP算法就能搞出来 证明自己YY吧 出题人卡精度丧心病狂... #include <cmath> #include <cstdio> #include <cstring> #inclu

bzoj 1355: [Baltic2009]Radio Transmission【kmp】

kmp复健,答案是n-next[n] #include<iostream> #include<cstdio> using namespace std; const int N=1000005; int n,ne[N]; char s[N]; int main() { scanf("%d%s",&n,s+1); int j=0; for(int i=2;i<=n;i++) { while(s[j+1]!=s[i]&&j) j=ne[j

bzoj 做起走 -- bzoj 1009 GT 考试

现在每次做一道bzoj上的题,整个人都感觉升华了... 先是在网上各种搜题解.要么只有代码,要么有点讲解看不懂,对于从来没有耐心看完别人代码的我,只能一篇一篇的翻..然后终于在某2011级同学的某段话中找到了灵感,把它给A了. 我还是好好记录一下这道题的做题过程,不要又被其他人喷"只有做过的人才看得懂了!" 首先说说这道题的思路吧:dp+矩阵优化.dp虽然不那么明显,但是做过了ac自动机上的dp之后也看得出来--kmp上的dp.具体怎么想到是dp的只能说是个人经验问题,做过一遍就容易做

[BZOJ 3236] [Ahoi2013] 作业 &amp;&amp; [BZOJ 3809] 【莫队 | 分块】

题目链接: BZOJ - 3236   BZOJ - 3809 算法一:莫队 首先,单纯的莫队算法是很好想的,就是用普通的第一关键字为 l 所在块,第二关键字为 r 的莫队. 这样每次端点移动添加或删除一个数字,用树状数组维护所求的信息就是很容易的.由于这里有 logn复杂度,所以复杂度还是挺高的. 于是 BZOJ-3236 的时限 100s,我的代码跑了 98s,险过...... However..BZOJ-3809 的出题人(SLYZ的神犇)就没有这么善良了!直接内存限制 28MB 就直接把

Bzoj 2453: 维护队列 &amp;&amp; Bzoj 2120: 数颜色 分块,bitset

2453: 维护队列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 578  Solved: 247[Submit][Status][Discuss] Description 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色.但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你