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: ...
随机推荐
- coursera网站中的VTT字幕的使用
coursera网站中的VTT字幕的使用 1.https://www.coursera.org/learn/os-virtsecurity/lecture/xuWgP/1-3-cao-zuo-xi-t ...
- Android 仿百度医生的智能分诊界面
http://blog.csdn.net/jiang89125/article/details/49622853
- checkbox设置复选框的只读效果不让用户勾选
在Web开发中,有时候需要显示一些复选框(checkbox),表明这个地方是可以进行勾选操作的,但是有时候是只想告知用户"这个地方是可以进行勾选操作的"而不想让用户在此处勾选(比如 ...
- [Java 8] (8) Lambda表达式对递归的优化(上) - 使用尾递归 .
递归优化 很多算法都依赖于递归,典型的比如分治法(Divide-and-Conquer).但是普通的递归算法在处理规模较大的问题时,常常会出现StackOverflowError.处理这个问题,我们可 ...
- 从零开始部署小型企业级虚拟桌面 -- Vmware Horizon View 6 For Linux VDI
环境说明 注,本套环境所用机器全部是64位的. 管理服务器载体:安装win7操作系统,通过VMware Workstation安装4台虚拟机,用作vCenter,Connection Server,D ...
- EF为什么向我的数据库再次插入已有对象?(ZT)
最近做了个多对多对实体对象,结果发现每次只要增加一个子实体,就会自动添加一个父实体进去,而不管该父实体是否已经存在. 找了好久,终于找到这篇文章,照文章内容来看,应该是断开连接导致的. 原文地址:ht ...
- 基于VueJS的render渲染函数结合自定义组件打造一款非常强大的IView 的Table
基于VueJS的render渲染函数结合自定义组件打造一款非常强大的IView 的Table https://segmentfault.com/a/1190000015970367
- Java数据结构和算法(二)--队列
上一篇文章写了栈的相关知识,而本文会讲一下队列 队列是一种特殊的线性表,在尾部插入(入队Enqueue),从头部删除(出队Dequeue),和栈的特性相反,存取数据特点是:FIFO Java中queu ...
- [CF] 37 E. Trial for Chief
如果固定了一个中心,那么只需要考虑从它开始最远染到的那些点究竟染了几次. 上下左右不同的点连1边,相同的连0边,跑单源最短路就可以啦. lyd讲的是统计到最远黑点+1的最小值,但是#58数据全是白点, ...
- python-列表数据类型内置方法
1 列表数据类型(必考) 1.1 用途:兴趣爱好,多个女朋友 1.2 定义方式:[]内用逗号隔开多个元素,多个元素可以是任意数据类型 fangping_boy_friend_list=['ruixin ...