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个)上的字母及猴子按下这个按钮的概率已知,而且猴 ...
随机推荐
- 17.3.12---xmlrpclib模块
1----XML-RPC是一种使用xml文本的方式利用http协议传输命令和数据的rpc基址,我们用pythom的想mlrpclib模块可以让程序与其他任何语言编写的XML-RPC服务器进行数据传输 ...
- PAT Advanced 1052 Linked List Sorting (25) [链表]
题目 A linked list consists of a series of structures, which are not necessarily adjacent in memory. W ...
- 一、早期(Early Stage)
一.早期(Early Stage) 如果单纯从零基础开始,早期(Early Stage)应该是一到两个月(由于英语与中文差异比与其他语言大,中国同学至少两个月,但也不应过长.我们的经验是一般中国同学会 ...
- Java之同步代码块处理继承Thread类的线程安全问题
package com.atguigu.java; /** *//** * 使用同步代码块解决继承Thread类的方式的线程安全问题 * * 例子:创建三个窗口卖票,总票数为100张.使用继承Thre ...
- 解决 nginx 启动错误 nginx: [emerg] host not found in upstream
解决办法来自于:https://blog.csdn.net/Hreticent/article/details/86074502 感谢这个朋友简单而清晰的解决办法. 在配置nginx支持PHP的时候, ...
- Anaconda环境安装
Anaconda环境安装 一.Anaconda Anaconda是Python的一个开源的发行版本,里面包含了很多科学计算相关的包,它和Python的关系就像linux系统中centos和Ubuntu ...
- grub.cfg文件编辑
grub2启动项里面找不到Windows的情况,这时候就需要自己去配置grub.cfg 在grub.cfg中加入如下代码: menuentry 'Windows Boot Manager (on /d ...
- Java连载72-String类详解、多个构造方法
一.String类 1.String类是不可以变类,也就是说String对象声明后 2.java.lang.String:是字符串类型 (1)字符串一旦创建不可再改变,“abc”字符串对象一旦创建,不 ...
- 吴裕雄--天生自然 pythonTensorFlow自然语言处理:交叉熵损失函数
import tensorflow as tf # 1. sparse_softmax_cross_entropy_with_logits样例. # 假设词汇表的大小为3, 语料包含两个单词" ...
- tc/traffic control 网络控制工具
第一个例子 增加延时 tc qdsic add dev enp0s3 root netem delay 200ms qdisc : queuing discipline, 当内核需要发送包到某个接口时 ...