BZOJ3172 [Tjoi2013]单词 字符串 SA ST表
原文链接http://www.cnblogs.com/zhouzhendong/p/9026543.html
题目传送门 - BZOJ3172
题意
输入$n(n\leq 200)$个字符串,保证长度总和$\leq 10^6$。
对于每一个字符串,求它在所有的$n$个字符串(包括它自己)中出现了几次。(同一个字符串内可能出现多次当前的字符串)
题解
听百度说这题可以用AC自动机??
然而我顺手大力$SA$干掉了此题。
本题用$SA$做好像很容易。
首先,把输入的字符串连接成一个字符串,不同的单词之间用特殊字符隔开。注意最终串长度是$1e6+n$级别的,数组别开小。
然后闭着眼睛$SA$啊。
记第$i$个串的开头为$p_i$,长度为$len_i$。
对于第$i$个串,就是从$rank_{p_i}$位置开始。向左,利用$height$表示的$lcp$长度,如果$lcp$长度不小于$len_i$,那么仍然可以继续向左扩张。向右同理。
这样好像就可以过掉了。
然而我却在搜百度前就写完了$ST$表……好像快了不少。
上一句为题外话。
向左向右一步一步扩张显然太慢,所以我们预处理$height$的$ST$表,然后倍增地走。每次走的复杂度为$O(\log m)$。
总复杂度$O((n+m)\log m)$。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=205,M=1000205;
int n,m=0,p[N],len[N];
int SA[M],rank[M],height[M],tmp[M],tax[M];
int ST[M][22];
char s[M];
void Sort(int n,int m){
for (int i=0;i<=m;i++)
tax[i]=0;
for (int i=1;i<=n;i++)
tax[rank[i]]++;
for (int i=1;i<=m;i++)
tax[i]+=tax[i-1];
for (int i=n;i>=1;i--)
SA[tax[rank[tmp[i]]]--]=tmp[i];
}
bool cmp(int rk[],int x,int y,int w){
return rk[x]==rk[y]&&rk[x+w]==rk[y+w];
}
void Suffix_Array(char s[],int n){
memset(SA,0,sizeof SA);
memset(tmp,0,sizeof tmp);
memset(rank,0,sizeof rank);
memset(height,0,sizeof height);
for (int i=1;i<=n;i++)
rank[i]=s[i],tmp[i]=i;
int m=127;
Sort(n,m);
for (int w=1,p=0;p<n;w<<=1,m=p){
p=0;
for (int i=n-w+1;i<=n;i++)
tmp[++p]=i;
for (int i=1;i<=n;i++)
if (SA[i]>w)
tmp[++p]=SA[i]-w;
Sort(n,m);
swap(rank,tmp);
rank[SA[1]]=p=1;
for (int i=2;i<=n;i++)
rank[SA[i]]=cmp(tmp,SA[i],SA[i-1],w)?p:++p;
}
for (int i=1,j,k=0;i<=n;height[rank[i++]]=k)
for (k=max(k-1,0),j=SA[rank[i]-1];s[i+k]==s[j+k];k++);
}
void Get_ST(int n){
memset(ST,0,sizeof ST);
for (int i=1;i<=n;i++){
ST[i][0]=height[i];
for (int j=1;j<22;j++){
ST[i][j]=ST[i][j-1];
if (i-(1<<(j-1))>0)
ST[i][j]=min(ST[i][j],ST[i-(1<<(j-1))][j-1]);
}
}
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%s",s+m+1);
p[i]=m+1,len[i]=strlen(s+m+1);
m+=len[i]+1;
s[m]='#';
}
Suffix_Array(s,m);
Get_ST(m);
for (int i=1;i<=n;i++){
int ans=1,pos=rank[p[i]],L=len[i];
for (int j=21,now=pos;j>=0;j--)
if (now-(1<<j)>0&&ST[now][j]>=L)
now-=1<<j,ans+=1<<j;
for (int j=21,now=pos;j>=0;j--)
if (now+(1<<j)<=m&&ST[now+(1<<j)][j]>=L)
now+=1<<j,ans+=1<<j;
printf("%d\n",ans);
}
return 0;
}
BZOJ3172 [Tjoi2013]单词 字符串 SA ST表的更多相关文章
- BZOJ2534 Uva10829L-gap字符串 字符串 SA ST表
原文链接https://www.cnblogs.com/zhouzhendong/p/9240665.html 题目传送门 - BZOJ2534 题意 有一种形如 $uvu$ 形式的字符串,其中 $u ...
- BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4556.html 题目传送门 - BZOJ4556 题意 给定一个长度为 $n$ 的字符串 $s$ . ...
- UOJ#219/BZOJ4650 [NOI2016]优秀的拆分 字符串 SA ST表
原文链接http://www.cnblogs.com/zhouzhendong/p/9025092.html 题目传送门 - UOJ#219 (推荐,题面清晰) 题目传送门 - BZOJ4650 题意 ...
- BZOJ3230 相似子串 字符串 SA ST表
原文链接http://www.cnblogs.com/zhouzhendong/p/9033092.html 题目传送门 - BZOJ3230 题意 给定字符串$s$.长度为$n$. 现在有$Q$组询 ...
- BZOJ2119 股市的预测 字符串 SA ST表
原文链接https://www.cnblogs.com/zhouzhendong/p/9069171.html 题目传送门 - BZOJ2119 题意 给定一个股票连续$n$个时间点的价位,问有多少段 ...
- 【bzoj3172】: [Tjoi2013]单词 字符串-AC自动机
[bzoj3172]: [Tjoi2013]单词 先用所有单词构造一个AC自动机 题目要求的是每个单词在这个AC自动机里匹配到的次数 每次insert一个单词的时候把路径上的cnt++ 那么点p-&g ...
- Codeforces Round #422 (Div. 2)E. Liar sa+st表+dp
题意:给你两个串s,p,问你把s分开顺序不变,能不能用最多k段合成p. 题解:dp[i][j]表示s到了前i项,用了j段的最多能合成p的前缀是哪里,那么转移就是两种,\(dp[i+1][j]=dp[i ...
- bzoj 3230: 相似子串【SA+st表+二分】
总是犯低级错误,st表都能写错-- 正反分别做一遍SA,预处理st表方便查询lcp,然后处理a[i]表示前i个后缀一共有多少个本质不同的子串,这里的子串是按字典序的,所以询问的时候直接在a上二分排名就 ...
- BZOJ3172 [Tjoi2013]单词 【AC自动机】
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 4293 Solved: 2083 [Submit][Stat ...
随机推荐
- MVC、MVP、MVVM模式
MVC,MVP和MVVM都是常见的软件架构设计模式(Architectural Pattern),它通过分离关注点来改进代码的组织方式.不同于设计模式(Design Pattern),只是为了解决一类 ...
- Light OJ 1214
简单大数模拟题: #include<bits/stdc++.h> using namespace std; typedef long long ll; string Num; vector ...
- Webapi 跨域 解决解决错误No 'Access-Control-Allow-Origin' header is present on the requested resource 问题
首先是web端(http://localhost:53784) 请求 api(http://localhost:81/api/)时出现错误信息: 查看控制台会发现错误:XMLHttpRequest c ...
- iOS weak 内存释放问题
我们都知道weak 关键字可以解决内存不释放问题,但是使用上有些讲究. 看代码: import UIKit var str = "Hello, playground" class ...
- Android录制音频的三种方式
对于录制音频,Android系统就都自带了一个小小的应用,可是使用起来可能不是特别的灵活.所以有提供了另外的俩种. 下边来介绍下这三种录制的方式; 1.通过Intent调用系统的录音器功能,然后在录制 ...
- OracleAES加密
OracleAES加密 (2012-04-29 21:52:15)转载▼标签: oracle aes 加密 it 分类: 开发-- 加密函数CREATE OR REPLACE FUNCTION FUN ...
- Confluence 6 用户宏示例 - NoPrint
这个示例演示了如何创建一个用户宏,这个宏包括了在查看页面中显示的内容,但是不被打印. Macro name noprint Visibility Visible to all users in the ...
- Zookeeper客户端Curator的使用,简单高效
Curator是Netflix公司开源的一个Zookeeper客户端,与Zookeeper提供的原生客户端相比,Curator的抽象层次更高,简化了Zookeeper客户端的开发量. 1.引入依赖: ...
- ubuntu sublime text 3 安装
#安装GPG wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add - #确保apt被设置为 ...
- Nginx详解二十四:Nginx深度学习篇之灰度发布
实战场景 - 灰度发布 灰度发布的作用:按照一定的关系区别,分部分的代码进行上线,使代码的发布能平滑过渡上线实现方式: 1.用户的信息cookie等信息区别 2.根据用户的IP地址 安装memcach ...