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: ...
随机推荐
- arttemplate模板引擎有假数据返回数据多层内嵌的渲染方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- http://bbs.chinaunix.net/thread-1463276-1-1.html
http://bbs.chinaunix.net/thread-1463276-1-1.html
- ubuntu下nginx+PHP-FPM安装配置
安装nginx apt-get install nginx 配置nginx 位置: /etc/nginx/nginx.conf ,其中包含了 include /etc/nginx/conf.d/*. ...
- git 初识
现在平时用的都是SVN,感觉还是挺好用的.就是有的时候解决冲突的时候有点麻烦.但这样也是不可避免的. 今天看来下GIT,同样是版本控制,GIT的原理,和SVN还是不一样的.我个人的理解,SVN是对每个 ...
- codevs 2905 足球晋级
时间限制: 1 s 空间限制: 64000 KB 题目等级 : 黄金 Gold 题目描述 Description A市举行了一场足球比赛 一共有4n支队伍参加,分成n个小组(每小组4支队伍)进 ...
- 李开复:AlphaGo 若打败了世界冠军,意味着什么?
创新工场董事长李开复在知乎就AlphaGo与李世石的人机大战发表了自己看法,他认为四个月前的AlphaGo击败李世石基本不可能,不过这四个月AlphaGo进步很多,比赛应该很精彩.但是,无论这次结果如 ...
- easybcd 支持 windows 10 和 ubuntu 14.04 双系统启动
家里计算机系统 windows 10 全新安装. 原本是双系统的,还有一个ubuntu. windows 10 安装以后,恢复ubuntu就是问题了. (事后经验:请不要立刻安装bcd修改工具) 最初 ...
- 遍历NSView下的子视图方法
如何遍历NSView下的子视图呢 for (NSView *aview in [SuperV subviews]) { if([aview isMemberOfClass:[NSButton clas ...
- sh脚本写法
1.shell注释符号: 1. 单行注释: “#” 2. 多行注释: : << ! 语句1 语句2 语句3 语句4 ! http://blog.csdn.net/lansesl2008/a ...
- spring boot 在idea中实现热部署
1)在pom中直接引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...