BZOJ2099: [Usaco2010 Dec]Letter 恐吓信
给两个长度不超过50000的串,A串可每次截连续一段复制出来,求最少复制几次能得到B串。
方法一:SAM。不会。
嗯好会了。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
//#include<iostream>
//#include<time.h>
using namespace std; int n,m;
#define maxn 200011*2
char s[maxn],p[maxn];
struct SAM
{
int ch[maxn][],size,last,pre[maxn],pos[maxn];
SAM()
{
size=;
memset(ch[],,sizeof(ch[]));
pre[]=-;
}
int idx(char c) {return c-'A';}
void insert(char c,int p)
{
int id=idx(c),x=++size;
memset(ch[x],,sizeof(ch[x])); pos[x]=p;
int y=last;
for (;y!=- && !ch[y][id];y=pre[y]) ch[y][id]=x;
last=x;
if (y==-) pre[x]=;
else
{
if (pos[ch[y][id]]==pos[y]+) pre[x]=ch[y][id];
else
{
int z=ch[y][id],w=++size;
memcpy(ch[w],ch[z],sizeof(ch[z]));
pos[w]=pos[y]+; pre[w]=pre[z];
pre[z]=pre[x]=w;
for (;y!=- && ch[y][id]==z;y=pre[y]) ch[y][id]=w;
}
}
}
}sam; int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
char c;while (!((c=getchar())>='A' && c<='Z'));
sam.insert(c,i);
}
for (int i=;i<=m;i++) while (!((p[i]=getchar())>='A' && p[i]<='Z'));
int pos=,ans=;
while (pos<=m)
{
int now=;
while (pos<=m && sam.ch[now][p[pos]-'A']) now=sam.ch[now][p[pos]-'A'],pos++;
// cout<<endl;
ans++;
}
printf("%d\n",ans);
return ;
}
方法二:其实就是拿B去A上面匹配若干次。多次匹配的话可以把A先建个后缀数组,然后每次二分到B的位置搞匹配。匹配一次怕太慢的话,用hash吧!二分匹配长度找到第一个不可匹配的位置,就可以算匹配长度啦!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
//#include<iostream>
using namespace std; int n,m;
#define maxn 50011
char t[maxn],p[maxn],c;
int ht[maxn],hp[maxn];
int sa[maxn],cnt[maxn],rank[maxn],y[maxn];
void makesa(char* s)
{
int n=strlen(s),m=;
for (int i=;i<m;i++) cnt[i]=;
for (int i=;i<n;i++) cnt[rank[i]=s[i]-'A']++;
for (int i=;i<m;i++) cnt[i]+=cnt[i-];
for (int i=n-;i>=;i--) sa[--cnt[rank[i]]]=i;
for (int k=;k<=n;k<<=)
{
int p=;
for (int i=n-k;i<n;i++) y[p++]=i;
for (int i=;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k;
for (int i=;i<m;i++) cnt[i]=;
for (int i=;i<n;i++) cnt[rank[y[i]]]++;
for (int i=;i<m;i++) cnt[i]+=cnt[i-];
for (int i=n-;i>=;i--) sa[--cnt[rank[y[i]]]]=y[i];
memcpy(y,rank,sizeof(y));
p=;rank[sa[]]=;
for (int i=;i<n;i++)
rank[sa[i]]=y[sa[i]]==y[sa[i-]] && ((sa[i]+k>=n && sa[i-]+k>=n)
|| (sa[i]+k<n && sa[i-]+k<n && y[sa[i]+k]==y[sa[i-]+k]))?p:++p;
if (p==n-) break;
m=p+;
}
}
void makeh(char* s,int* h)
{
int n=strlen(s);
h[]=s[]-'A';
for (int i=;i<n;i++)
h[i]=h[i-]*+s[i]-'A';
}
int pw[maxn];
void makepw(int n)
{
pw[]=;
for (int i=;i<=n;i++)
pw[i]=pw[i-]*;
}
bool ok(int x,int y)
{
int L=,R=min(n-x,m-y);
while (L<R)
{
if (ht[x+mid-]-ht[x-]*pw[mid]==hp[y+mid-]-hp[y-]*pw[mid]) L=mid;
else R=mid-;
}
return p[y+L]<=t[x+L];
}
int lcp(int x,int y)
{
int now=;
while (x<n && y<m && t[x]==p[y]) now++,x++,y++;
return now;
}
void play(int &x)
{
int L=,R=n;
while (L<R)
{
int mid=(L+R)>>;
if (ok(sa[mid],x)) R=mid;
else L=mid+;
}
if (!L) x+=lcp(sa[L],x);
else if (L<n) x+=max(lcp(sa[L-],x),lcp(sa[L],x));
else x+=lcp(sa[n-],x);
}
bool isalpha(char c) {return c>='A' && c<='Z';}
int main()
{
scanf("%d%d",&n,&m);
t[n]='\0';p[m]='\0';
for (int i=;i<n;i++)
{
while (!isalpha(c=getchar()));
t[i]=c;
}
for (int i=;i<m;i++)
{
while (!isalpha(c=getchar()));
p[i]=c;
}
makesa(t);
makeh(t,ht);makeh(p,hp);makepw(max(n,m));
int now=,ans=;
while (now<m) play(now),ans++;
printf("%d\n",ans);
return ;
}
BZOJ2099: [Usaco2010 Dec]Letter 恐吓信的更多相关文章
- BZOJ_2099_[Usaco2010 Dec]Letter 恐吓信_后缀自动机+贪心
BZOJ_2099_[Usaco2010 Dec]Letter 恐吓信_后缀自动机 Description FJ刚刚和邻居发生了一场可怕的争吵,他咽不下这口气,决定佚名发给他的邻居 一封脏话连篇的信. ...
- 【BZOJ】2099: [Usaco2010 Dec]Letter 恐吓信
[题意]给定长度为n和m的两个字符串S和T,要求在字符串S中取出若干段拼成T(可重复取),求最小段数,n,m<=50000. [算法]后缀自动机 || 后缀数组 [题解]对串S建SAM,然后在上 ...
- BZOJ2097[Usaco2010 Dec] 奶牛健美操
我猜我这样继续做水题会狗带 和模拟赛的题很像,贪心搞一下. #include<bits/stdc++.h> using namespace std; int read(){ ,f=;cha ...
- BZOJ2101: [Usaco2010 Dec]Treasure Chest 藏宝箱
2101: [Usaco2010 Dec]Treasure Chest 藏宝箱 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 327 Solved: ...
- BZOJ 2100: [Usaco2010 Dec]Apple Delivery( 最短路 )
跑两遍最短路就好了.. 话说这翻译2333 ---------------------------------------------------------------------- #includ ...
- BZOJ 2101: [Usaco2010 Dec]Treasure Chest 藏宝箱( dp )
dp( l , r ) = sum( l , r ) - min( dp( l + 1 , r ) , dp( l , r - 1 ) ) 被卡空间....我们可以发现 l > r 是无意义的 ...
- 2102: [Usaco2010 Dec]The Trough Game
2102: [Usaco2010 Dec]The Trough Game Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 117 Solved: 84[ ...
- BZOJ_2097_[Usaco2010 Dec]Exercise 奶牛健美操_二分答案+树形DP
BZOJ_2097_[Usaco2010 Dec]Exercise 奶牛健美操_二分答案+树形DP Description Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的 ...
- bzoj2101【Usaco2010 Dec】Treasure Chest 藏宝箱
2101: [Usaco2010 Dec]Treasure Chest 藏宝箱 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 418 Solved: ...
随机推荐
- AJPFX关于StringBuffer,StringBuilder类总结(二)
StringBuffer,StringBuilder类 总结2需要注意的知识点:1):// String -- >StringBuffer String s = "hel ...
- Spring Cloud Config 使用Bus的动态配置中心
server端配置 POM文件 <dependency> <groupId>org.springframework.boot</groupId> <artif ...
- Android系统固件定制方式
target_product.mkAndroid系统在构建关于某种产品的固件时,一般会根据特定于该产品的具体target_product.mk来配置生成整个Android系统./target_prod ...
- 1.ssm web项目中的遇到的坑--自定义JQuery插件(slide menu)
自定义的JQuery插件写的回调函数不执行: 写好了回调函数,将函数打印出来是原形,就是不执行 function () { console.log("---onClickItem---&qu ...
- 利用条件运算符的嵌套来完成此题: 学习成绩>= 90分的同学用A表示, 60-89分之间的用B表示, 60分以下的用C表示。
题目:利用条件运算符的嵌套来完成此题: 学习成绩>= 90分的同学用A表示, 60-89分之间的用B表示, 60分以下的用C表示. 程序分析:(a> b)?a:b这是条件运算符的基本例子. ...
- 写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度
import java.util.Scanner; /** * [程序38] * * 题目:写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度. * * @author Jame ...
- Low Speed High Torque Hydraulic Motor: Motion Performance
Crank connecting rod type low speed high torque hydraulic motor is used earlier, which is called Sta ...
- 任务二:零基础HTML及CSS编码(一)
面向人群: 零基础或初学者 难度: 简单 重要说明 百度前端技术学院的课程任务是由百度前端工程师专为对前端不同掌握程度的同学设计.我们尽力保证课程内容的质量以及学习难度的合理性,但即使如此,真正决定课 ...
- Oracle数据库日常SQL的使用
DDL 语句(数据定义语言Create.Alter. Drop.Truncate) 1.建表:create table 表名(): 2.复制表结构及其数据:create table 新表名 as se ...
- 【MySQL】索引和锁
前言 本文摘自数据库两大神器[索引和锁] 声明:如果没有说明具体的数据库和存储引擎,默认指的是MySQL中的InnoDB存储引擎 索引 在之前,我对索引有以下的认知: 索引可以加快数据库的检索速度 表 ...