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个)上的字母及猴子按下这个按钮的概率已知,而且猴 ...
随机推荐
- java求两个圆相交坐标
最近由于项目需要,根据两个圆函数求出相交的坐标.实现代码如下,另感谢两圆求交点算法实现Java代码,虽然他所贡献的代码中存在问题,但仍有借鉴意义. 1.两个圆相交的数学求法 在中学数学中我们知道,一个 ...
- 201512-1 数位之和 Java
思路: mod 10获取最低位,除以10去掉最低位 import java.util.Scanner; public class Main { public static void main(Stri ...
- 国产手机早就异军突起,为何还是有很多人“迷恋”iPhone?
近几年,国产手机不论是从外观上还是设计上,以及销量上都比前有了长足的进步,手机的品质和售后也在不断提升.这也让中国手机厂商不断的推出了拥有自己品牌特色的产品.特别是2018年不少国产手机品牌的旗舰级产 ...
- [ZJOI2006]书架(二分+树状数组)
这题90%以上的人做法为裸的平衡树,实际上根本没必要还常数大,最好的方法是二分+树状数组.具体做法是,开3倍内存,初始把中间n位赋值为1.对于每个操作:1&2.删除该位,将其丢在头/尾(开三倍 ...
- python爬虫王者荣耀高清皮肤大图背景故事通用爬虫
wzry-spider python通用爬虫-通用爬虫爬取静态网页,面向小白 基本上纯python语法切片索引,少用到第三方爬虫网络库 这是一只小巧方便,强大的爬虫,由python编写 主要实现了: ...
- 浙江省赛 ZOJ - 4033
题意: 第一行给出T代表有几个测试样例, 第二行给出n代表有几个人, 第三行给出一个由0和1组成的字符串,0代表女生,1代表男生. 并且第i个人有i个宝石. 现在要把这些人分为四组,G1 G2 两组是 ...
- HDU-4004 The Frog's Games (分治)
http://acm.hdu.edu.cn/showproblem.php?pid=4004 Problem Description The annual Games in frogs' kingdo ...
- 日期控件 My97DatePicker WdatePicker 日期格式
WdatePicker()只显示日期 WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss'})显示日期和时间 WdatePicker({dateFmt:'yyyy-MM ...
- 理解Java中的对象,变量和方法
1.对象的创建和销毁 1.1 对象的创建 这里只介绍创建对象与构造方法的关系 (1).每实例化一个对象就会自动调用一次构造方法,实质上这个过程就是创建对象的过程,准确的说,在Java语言中使用new操 ...
- Windows系统清理
@echo off del/f/s/q %systemdrive%\*.tmp del/f/s/q %systemdrive%\*._mp del/f/s/q %systemdrive%\*.log ...