DP × KMP
几道用到KMP的DP题:
hdu 5763 hdu 3689 hdu 3336 codeforces 494B codevs 3945
关于KMP的nx数组:
如果在本文中看见了nx[]指的是所谓“成功指针”,或者getnx()函数跟本人之前的板子写的不一样......
都是因为求nx数组有两种方法!!!
详情请阅本人的另一篇文章:关于KMP算法的重大发现
好了我们进入正题~
一道一道来~
hdu 5763 Another Meaning
题意及样例:原题链接
设第一个串为A,长为n;第二个串为B,长为L
从1到n计算1~k能代表的意思的数量f[k]
如果A[k-L+1,k]==B
则f[k]=f[k-L]+f[k-1]
否则f[k]=f[k-1]
判断A[k-L+1,k]是否与B匹配就要靠KMP了
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 1000000007
using namespace std; int t,al,bl;
char a[];
char b[];
int nx[];
int fl[];
int f[]; void getnx()
{
nx[]=;
for(int i=,j=;i<=bl;)
{
nx[i]=j;
while(j&&b[j]!=b[i])j=nx[j];
j++,i++;
}
} void kmp()
{
for(int i=,j=;i<=al;)
{
while(j&&b[j]!=a[i])j=nx[j];
if(j==bl)
{
fl[i]=;
j=nx[j];
}
else j++,i++;
}
} int main()
{
scanf("%d",&t);
for(int cs=;cs<=t;cs++)
{
memset(a,,sizeof(a));
memset(b,,sizeof(b));
memset(fl,,sizeof(fl));
scanf("%s",a+);
scanf("%s",b+);
al=strlen(a+);
bl=strlen(b+);
getnx();
kmp();
f[]=;
for(int i=;i<=al;i++)
{
if(fl[i])f[i]=(f[i-]+f[i-bl])%mod;
else f[i]=f[i-];
}
printf("Case #%d: %d\n",cs,f[al]);
}
return ;
}
hdu 5763 Another Meaning
hdu 3689 Infinite monkey theorem
概率DP,不一定一出错就要重头开始打。用nx[ ]数组转移,避免字符的浪费。
这里的nx[ ]数组指的是成功指针......(玄学)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n,m,len;
double p[];
char s[];
char key[];
int nx[];
double f[][]; void getnx()
{
nx[]=;
for(int i=,j=;i<=len;i++)
{
while(j&&s[i]!=s[j+])j=nx[j];
if(s[j+]==s[i])j++;
nx[i]=j;
}
} int main()
{
while(true)
{
memset(nx,,sizeof(nx));
for(int i=;i<=;i++)p[i]=0.00;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
f[i][j]=0.00;
}
}
scanf("%d%d",&n,&m);
if(!n)return ;
for(int i=;i<=n;i++)
{
char c[];
scanf("%s",c+);
key[i]=c[];
scanf("%lf",&p[i]);
}
scanf("%s",s+);
len=strlen(s+);
getnx();
f[][]=1.00;
for(int i=;i<=m;i++)
{
for(int j=;j<len;j++)
{
for(int k=;k<=n;k++)
{
int ps=j;
while(ps&&s[ps+]!=key[k])ps=nx[ps];
if(s[ps+]==key[k])ps++;
f[i][ps]+=f[i-][j]*p[k];
}
}
}
double ans=0.00;
for(int i=;i<=m;i++)ans+=f[i][len];
printf("%.2lf%%\n",ans*100.00);
}
}
hdu 3689 Infinite monkey theorem
hdu 3336 Count the string
利用KMP中nx[ ]数组的性质。
上代码。
#include<cstdio>
#include<cstring>
using namespace std; int t,n,len,f[],ans;
char s[];
int nx[]; void getnx()
{
for(int i=;i<n;i++)
{
int j=nx[i];
while(j&&s[i]!=s[j]) j=nx[j];
nx[i+]= s[i]==s[j] ? j+:;
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%s",s);
len=strlen(s);
getnx();
memset(f,,sizeof(f));
ans=;
for(int i=;i<=n;i++)
{
f[i]=f[nx[i]]+;
ans+=f[i];
f[i]%=;
ans%=;
}
printf("%d\n",ans);
}
}
hdu 3336 Count the string
CodeForces 494B Obsessive String
比较复杂......
记录f[ ],f[ ]的前缀和s[ ],还有s[ ]的前缀和ss[ ] 。
KMP用来匹配字符串。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 1000000007
using namespace std; char a[],b[];
int al,bl;
int nx[];
int fl[];
int f[],s[],ss[]; void getnx()
{
nx[]=;
for(int i=,j=;i<=bl;)
{
nx[i]=j;
while(j&&b[j]!=b[i])j=nx[j];
i++,j++;
}
} void kmp()
{
for(int i=,j=;i<=al;)
{
while(j&&a[i]!=b[j])j=nx[j];
if(j==bl)fl[i]=,j=nx[j];
else i++,j++;
}
} int main()
{
scanf("%s",a+);
al=strlen(a+);
scanf("%s",b+);
bl=strlen(b+);
getnx();
kmp();
for(int i=;i<=al;i++)
{
if(fl[i])f[i]=(i-bl++ss[i-bl])%mod;
else f[i]=f[i-];
s[i]=(s[i-]+f[i])%mod;
ss[i]=(ss[i-]+s[i])%mod;
}
int ans=;
for(int i=;i<=al;i++)ans=(ans+f[i])%mod;
printf("%d",ans);
}
CodeForces 494B Obsessive String
CODEVS 3945 完美拓印
当成字符串匹配......
坑挺多的,各种方向都得匹配一次求出答案。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int a[],b[],s1[],s2[],nx[];
int n,m,ans; void getnx()
{
nx[]=nx[]=;
for(int i=;i<n;i++)
{
int j=nx[i];
while(j&&s1[i]!=s1[j])j=nx[j];
nx[i+]=(s1[i]==s1[j]?j+:);
}
} int kmp()
{
getnx();
int j=,cnt=;
for(int i=;i<m;i++)
{
while(j&&s2[i]!=s1[j])j=nx[j];
if(s2[i]==s1[j])j++;
if(j==n)cnt++,j=nx[j];
}
return cnt;
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)scanf("%d",&a[i]);
for(int i=;i<m;i++)scanf("%d",&b[i]);
if(n==)
{
printf("%d\n",m<<);
return ;
}
n--; m--;
for(int i=;i<n;i++)s1[i]=a[i+]-a[i];
for(int i=;i<m;i++)s2[i]=b[i+]-b[i];
ans+=kmp();
for(int i=;i<n;i++)s1[i]=a[n-i]-a[n-i-];
ans+=kmp();
for(int i=;i<n;i++)s1[i]=;
ans+=*kmp();
printf("%d",ans);
return ;
}
CODEVS 3945 完美拓印
结束了。
最后顺便说,有些字符串匹配的题可以用hash做。
这样可以偷懒,不用写KMP
好吧还是乖乖背KMP板子吧。
溜了。
DP × KMP的更多相关文章
- BZOJ1009GT考试 DP + KMP + 矩陣快速冪
@[DP, KMP, 矩陣快速冪] Description 阿申准备报名参加GT考试,准考证号为\(N\)位数\(X_1 X_2 .. X_n(0 <= X_i <= 9)\),他不希望准 ...
- CF 346B. Lucky Common Subsequence(DP+KMP)
这题确实很棒..又是无想法..其实是AC自动机+DP的感觉,但是只有一个串,用kmp就行了. dp[i][j][k],k代表前缀为virus[k]的状态,len表示其他所有状态串,处理出Ac[len] ...
- bzoj 1009 [HNOI2008]GT考试(DP+KMP+矩阵乘法)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1009 [题意] 给定一个字符串T,问长度为n且不包含串T的字符串有多少种. [思路] ...
- hdu-3689 Infinite monkey theorem 概率dp+kmp
有一只猴子随机敲键盘,给出它可能敲的键以及敲各个键的概率. 输入:n,表示有多少个键,m,表示猴子会敲m次键 n个二元组(字母,数字) 表示键代表的字母及其被敲的概率. 最后一个目标字符串. 问这只猴 ...
- 4572: [Scoi2016]围棋 轮廓线DP KMP
国际惯例的题面:这种题目显然DP了,看到M这么小显然要状压.然后就是具体怎么DP的问题.首先我们可以暴力状压上一行状态,然后逐行转移.复杂度n*3^m+3^(m*2),显然过不去. 考虑状态的特殊性, ...
- 5.Longest Palindromic Substring (String; DP, KMP)
Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...
- codeforces 825F F. String Compression dp+kmp找字符串的最小循环节
/** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: d ...
- 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优 ...
- HDU 5763 Another Meaning dp+字符串hash || DP+KMP
题意:给定一个句子str,和一个单词sub,这个单词sub可以翻译成两种不同的意思,问这个句子一共能翻译成多少种不能的意思 例如:str:hehehe sub:hehe 那么,有**he.he** ...
- HDU3689 Infinite monkey theorem 无限猴子(字符串DP+KMP)
题目描述: 大概的意思就是根据无限猴子定理,无限只猴子坐在打字机旁瞎敲,总有一个能敲出莎士比亚文集.现在给你一个打字机和一只猴子,打字机的每个按钮(共n个)上的字母及猴子按下这个按钮的概率已知,而且猴 ...
随机推荐
- 吴裕雄--天生自然ShellX学习笔记:Shell 数组
数组中可以存放多个值.Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似). 与大部分编程语言类似,数组元素的下标由0开始. Shell 数组用括号来 ...
- Django专题-Cookie
Cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响, ...
- 了解Kafka生产者
了解Kafka生产者 之前对kafka的整体架构有浅显的了解,这次正好有时间,准备深入了解一下kafka,首先先从数据的生产者开始吧. 生产者的整体架构 可以看到整个生产者进程主要由两个线程进 ...
- Less(7)
1.先判断注入类型 (1)首先看到要求,要求传一个ID参数,并且要求是数字型的:?id=1 (2)再输入:?id=1 and 1=1 (3)输入:?id=1 and 1=2 因为(2)(3)没有变化, ...
- 吴裕雄--天生自然 JAVA开发学习:继承
class 父类 { } class 子类 extends 父类 { } public class Penguin { private String name; private int id; pub ...
- Python语言学习前提:循环语句
一.循环语句 1.循环语句:允许执行下一个语句或语句组多次 2. 循环类型 3. 循环控制语句 4. while 循环语句 a.while循环语句:在某个条件下,循环执行某段程序,以处理需要重复处理的 ...
- [CTS2019]珍珠(NTT+生成函数+组合计数+容斥)
这题72分做法挺显然的(也是我VP的分): 对于n,D<=5000的数据,可以记录f[i][j]表示到第i次随机有j个数字未匹配的方案,直接O(nD)的DP转移即可. 对于D<=300的数 ...
- VMware 三种网络配置解释
https://blog.csdn.net/noob_f/article/details/51099040 ifconfig -a 网卡名称
- 计算机数制与IPv4
常用计数:十进制数 1010D.二进制 1010B.十六进制1010H 计算机数制: 数制组成=每一位上的数字*该位的值 IPV4地址一共32bit 人使用点分十进制的方式来进行记忆 IPv6地址一共 ...
- 关于dubbo接口性能测试
最初的压测这个dubbo接口有三种思路: .第一种就是基于业务,比如注册业务,注册成功后,会发送短信消息到用户手机,通过业务调用消息服务,最容易实现,但是业务瓶颈最大导致测试结果不准 .第二种是通 ...