BZOJ 3172([Tjoi2013]单词-后缀数组第一题+RMQ)
3172: [Tjoi2013]单词
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 268
Solved: 145
[
Submit][
Status]
Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文
中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
a
aa
aaa
Sample Output
3
1
上一次写RMQ是什么时候?(喂,离题了)
好吧……
第一题后缀数组
不想写下去了……(快哭了TNT)
这题在BZOJ上内存很容易开过(5人组-》TLE/CE/MLE/RE/AC)
大家要是这题RE把数组开小点。别忘了[RMQ*20]数组+数组之和 //省空间
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<cmath>
#include<cctype>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define RepD(i,n) for(int i=n;i>=0;i--)
#define MEM(a) memset(a,0,sizeof(a))
#define MEMI(a) memset(a,127,sizeof(a))
#define MEMi(a) memset(a,128,sizeof(a))
#define INF (2139062143)
#define F (1000000009)
#define MAXN (300+10)
#define MAXL (1000200+10)
#define eps (1e-9)
typedef long long ll;
char s[MAXL];
int n,pre[MAXN],tai[MAXN];
int w[MAXL],sa[MAXL],wa[MAXL*2]={0},wb[MAXL*2]={0};
// x-->上一行 y->下一行sa右值 wv-->y的左值 sa-->上次排名(求)
bool cmp(int *a,int x,int y,int l){return (a[x]==a[y]&&a[x+l]==a[y+l]);}
void suffix_array(int n,int m)
{
int *x=wa,*y=wb;
For(i,m) w[i]=0;
For(i,n) w[x[i]=s[i]]++;
Fork(i,2,m) w[i]+=w[i-1];
ForD(i,n) sa[w[x[i]]--]=i;
for(int j=1,p=0;p<n;j*=2,m=p)
{ p=0;
Fork(i,n-j+1,n) y[++p]=i;
For(i,n) if (j<sa[i]) y[++p]=sa[i]-j; For(i,m) w[i]=0;
For(i,n) w[x[i]]++;
For(i,m) w[i]+=w[i-1]; ForD(i,n) sa[w[x[ y[i] ]]--]=y[i];
//y is release p=y[sa[1]]=1;
Fork(i,2,n)
y[sa[i]]=(p+=(!cmp(x,sa[i-1],sa[i],j))); int *t=x;x=y;y=t;
}
}
int height[MAXL],rank[MAXL]; //height[i] 表示 sa[i]与sa[i-1]的最长公共前缀
void make_height(char *s,int n)
{
For(i,n) rank[sa[i]]=i;
For(i,n)
{
if (rank[i]==1) continue; //求height[rank[i]]
int j=max(0,height[rank[i-1]]-1),k=sa[rank[i]-1];
while (s[i+j]==s[k+j]) j++;
height[rank[i]]=j;
}
}
int bin[MAXN]={0},f[MAXL][24]={0};
int lcp(int l,int r)
{
int len=r-l+1,j=(int)log2(len);
return min(f[l][j],f[r-bin[j]+1][j]);
}
int main()
{
// freopen("bzoj3172.in","r",stdin);
scanf("%d",&n);pre[1]=1;
For(i,n)
{
scanf("%s",s+pre[i]);
tai[i]=strlen(s+pre[i]);
s[pre[i]+tai[i]]='#';
pre[i+1]=pre[i]+tai[i]+1;
}
s[pre[n+1]]=0; suffix_array(pre[n+1]-1,200); make_height(s,pre[n+1]-1); int logn=int(log2((double)pre[n+1]-1)+1);
bin[0]=1;
For(i,logn) bin[i]=bin[i-1]<<1;
For(i,pre[n+1]-1) f[i][0]=height[i]; For(j,logn)
For(i,pre[n+1]-1-(1<<j)+1)
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); For(i,n)
{
int tot=1;
int j=rank[pre[i]]+1;
{
int l=2,r=j-1,ans=0;
while (l<=r)
{
int m=l+r>>1;
if (lcp(m,j-1)>=tai[i]) ans=m,r=m-1;
else l=m+1;
}
if (ans) ans=j-1-ans+1;
tot+=ans;
}
{
int l=j,r=pre[n+1]-1,ans=0;
while (l<=r)
{
int m=l+r>>1;
if (lcp(j,m)>=tai[i]) ans=m,l=m+1;
else r=m-1;
}
if (ans) ans=ans-j+1;
tot+=ans;
}
cout<<tot<<endl;
}
// while (1);
return 0;
}
BZOJ 3172([Tjoi2013]单词-后缀数组第一题+RMQ)的更多相关文章
- BZOJ 3172 Tjoi2013 单词 后缀数组
题目大意:给定一个n个单词的文章,求每一个单词在文章中的出现次数 文章长度<=10^6(不是单词长度<=10^6,不然读入直接超时) 首先将全部单词用空格连接成一个字符串.记录每一个单词的 ...
- BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3198 Solved: 1532[Submit][Status ...
- bzoj 3172: [Tjoi2013]单词 AC自动机
3172: [Tjoi2013]单词 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- ●BZOJ 3172 [Tjoi2013]单词
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3172 题解: 把单词逐个接起来,中间用互不相同的字符连接,并记录下每个单词的首字母在串中的位 ...
- [BZOJ 3172] [Tjoi2013] 单词 【AC自动机】
题目链接:BZOJ - 3172 题目分析: 题目要求求出每个单词出现的次数,如果把每个单词都在AC自动机里直接跑一遍,复杂度会很高. 这里使用AC自动机的“副产品”——Fail树,Fail树的一个性 ...
- BZOJ 3172 [Tjoi2013]单词 AC自己主动机(fail树)
题意:链接 方法:AC自己主动机与fail树性质 解析:复习AC自己主动机的第一道题?(真正的第一题明明是又一次写了遍hdu2222! ) 这题说实话第一眼看上去就是个sb题,仅仅要建出来自己主动机. ...
- 【刷题】BZOJ 3172 [Tjoi2013]单词
Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N ...
- bzoj 3172 [Tjoi2013]单词(fail树,DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3172 [题意] 题目的意思是这样的,给若干个单词,求每个单词在这一堆单词中的出现次数. ...
- BZOJ 3172 [Tjoi2013]单词 AC自动机Fail树
题目链接:[http://www.lydsy.com/JudgeOnline/problem.php?id=3172] 题意:给出一个文章的所有单词,然后找出每个单词在文章中出现的次数,单词用标点符号 ...
随机推荐
- Oracle ACL(Access Control List)
在oralce 11g中假如你想获取server的ip或者hostname,执行如下语句 SELECT utl_inaddr.get_host_address FROM dual; //获取IP S ...
- 11 款最好 CSS 框架 让你的网站独领风骚
网页设计和发展领域已经成为竞争激烈的虚拟世界.想要在网络的虚拟世界中生存,仅有一堆静止的在线网络应用是远远不够的,网页必须要有很多功能,配以让人无法抗拒的设计.网页编码一定要合适.精确,才能保证不发生 ...
- 如何制作python安装模块(setup.py)
Python模块的安装方法: 1. 单文件模块:直接把文件拷贝到$python_dir/lib 2. 多文件模块,带setup.py:python setup.py install 3. egg文件, ...
- Java中替代C# ref/out 关键字方案:
刚学习Java不久,今天遇到一个问题,需要在方法中修改传入的对象的值,确切的说是需要使用一个方法,创建一个对象,并把其引用返回,熟悉C#的我的第一反应就是C#中的ref/out关键字,结果发现Java ...
- 依赖注入(DI)有助于应用对象之间的解耦,而面向切面编程(AOP)有助于横切关注点与所影响的对象之间的解耦(转good)
依赖注入(DI)有助于应用对象之间的解耦,而面向切面编程(AOP)有助于横切关注点与所影响的对象之间的解耦.所谓横切关注点,即影响应用多处的功能,这些功能各个应用模块都需要,但又不是其主要关注点,常见 ...
- java学习笔记11--Annotation
java学习笔记11--Annotation Annotation:在JDK1.5之后增加的一个新特性,这种特性被称为元数据特性,在JDK1.5之后称为注释,即:使用注释的方式加入一些程序的信息. j ...
- 主流JavaScript框架(Dojo、Google Closure、jQuery、Prototype、Mootools和YUI)的分析和对比
本文主要选取了目前比较流行的JavaScript框架Dojo.Google Closure.jQuery.Prototype.Mootools和YUI进行对比,主要是根据网上的资料整理而成,希望可以供 ...
- java 获取当期时间之前几小时的时间
Calendar expireDate = Calendar.getInstance(); expireDate.set(Calendar.HOUR_OF_DAY, expireDate.get(Ca ...
- web开发性能优化---用户体验篇
怎样从技术角度怎样增强用户体验.都是非常多平台都在做的事情,依据个人实际经验碰到几种体验做下总结. 1.降低页面刷新白屏 适当使用ajax技术.改善刷新白屏现象. 2.信息提醒,邮件.站内信.短信在购 ...
- 新出台的治理iMessage垃圾短信的规则
工信部拟制定<通信短信息服务管理规定>,为治理垃圾短信提供执法根据.当中,对于苹果iMessage垃圾信息泛滥现象,工信部也将跟踪研究技术监測和防范手段.这意味着长期以来处于监管" ...