给两个长度不超过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 恐吓信的更多相关文章

  1. BZOJ_2099_[Usaco2010 Dec]Letter 恐吓信_后缀自动机+贪心

    BZOJ_2099_[Usaco2010 Dec]Letter 恐吓信_后缀自动机 Description FJ刚刚和邻居发生了一场可怕的争吵,他咽不下这口气,决定佚名发给他的邻居 一封脏话连篇的信. ...

  2. 【BZOJ】2099: [Usaco2010 Dec]Letter 恐吓信

    [题意]给定长度为n和m的两个字符串S和T,要求在字符串S中取出若干段拼成T(可重复取),求最小段数,n,m<=50000. [算法]后缀自动机 || 后缀数组 [题解]对串S建SAM,然后在上 ...

  3. BZOJ2097[Usaco2010 Dec] 奶牛健美操

    我猜我这样继续做水题会狗带 和模拟赛的题很像,贪心搞一下. #include<bits/stdc++.h> using namespace std; int read(){ ,f=;cha ...

  4. BZOJ2101: [Usaco2010 Dec]Treasure Chest 藏宝箱

    2101: [Usaco2010 Dec]Treasure Chest 藏宝箱 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 327  Solved:  ...

  5. BZOJ 2100: [Usaco2010 Dec]Apple Delivery( 最短路 )

    跑两遍最短路就好了.. 话说这翻译2333 ---------------------------------------------------------------------- #includ ...

  6. BZOJ 2101: [Usaco2010 Dec]Treasure Chest 藏宝箱( dp )

    dp( l , r ) = sum( l , r ) - min( dp( l + 1 , r ) , dp( l , r - 1 ) ) 被卡空间....我们可以发现 l > r 是无意义的 ...

  7. 2102: [Usaco2010 Dec]The Trough Game

    2102: [Usaco2010 Dec]The Trough Game Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 117  Solved: 84[ ...

  8. BZOJ_2097_[Usaco2010 Dec]Exercise 奶牛健美操_二分答案+树形DP

    BZOJ_2097_[Usaco2010 Dec]Exercise 奶牛健美操_二分答案+树形DP Description Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的 ...

  9. bzoj2101【Usaco2010 Dec】Treasure Chest 藏宝箱

    2101: [Usaco2010 Dec]Treasure Chest 藏宝箱 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 418  Solved: ...

随机推荐

  1. AJPFX:求两个城市之间的距离

    键盘录入多个城市: 城市1,城市2,城市3  以 ### 结束输出然后再键盘录入各个城市之间的距离:  格式如下:0,12,4512,0,2245,22,0### 然后按照输入的两个城市,求得两个城市 ...

  2. poj1724 ROADS

    题意: N个城市,编号1到N.城市间有R条单向道路.每条道路连接两个城市,有长度和过路费两个属性.Bob只有K块钱,他想从城市1走到城市N.问最短共需要走多长的路.如果到不了N,输出-12<=N ...

  3. B/S网络架构

    B/S基于统一的应用层协议HTTP来交互数据,目前的B/S网络架构大多采用如图所示的架构设计,既要满足海量用户访问请求,又要保持用户请求的快速响应. 当一个用户在浏览器输入www.taobao.com ...

  4. Quartz使用一 通过getJobDataMap传递数据

    Quartz定时器使用比较广泛,介绍一点简单的使用 上代码:定义一个Job,执行具体的任务 package org.tonny.quartz; import java.text.SimpleDateF ...

  5. iOS端架构、基本组成与使用说明

    一. app整体描述 app的描述:需求文档+接口文档+程序架构. 说明:新入手的开发人员必须拿到这三个说明文档才能整体了解app功能. 二.app架构描述 1.架构视图 2.分层结构说明 [1] a ...

  6. 用户交互和if条件判断、嵌套

    #a=input("提示语“)#接受的数据类型是字符串str#提示用户输入姓名 # a=input("请输入姓名") print(a) '''输出结果:请输入姓名小明 姓 ...

  7. python基础一 day4 字典

    增加:   结果 删:  结果: 结果:   返回值是一个元组形式的键值   改: 结果: 结果:                                      代码: info=inpu ...

  8. faster rcnn训练过程讲解

    http://blog.csdn.net/u014696921/article/details/60321425

  9. C++中:点运算符和箭头运算符的区别

    点运算符用于获取对象成员: 箭头运算符用于获取指针指向的对象的成员: 例如: std::string s1 = "string"; std::string *p = &s1 ...

  10. upupoo(网页壁纸)自主修改一:农历

    最近在使用一款upupoo的壁纸软件,感觉还可以,主要是对其中html可设置为壁纸方面情有独钟 前几天在它的网页区发现了一个壁纸,感觉挺好: 感觉内容有点少,今天在工作空余时间就在其中加上了农历,同时 ...