bzoj1396 识别子串【解法一】
来源:互联网 发布:java 汉字验证码 编辑:程序博客网 时间:2024/06/07 00:14
解法一【后缀数组+单调队列】见【这里】。
考虑对于一个位置
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=1000010,oo=0x3f3f3f3f;char s[maxn];int sa[maxn],rank[maxn],height[maxn],f[maxn],cnt[maxn],tag1[maxn],tag2[maxn],val[maxn],n;void init(int p,int L,int R){ tag1[p]=tag2[p]=oo; if (L<R) { int mid=L+R>>1; init(p<<1,L,mid); init(p<<1|1,mid+1,R); }}void modi1(int p,int L,int R,int l,int r,int x){ if (l<=L&&R<=r) tag1[p]=min(tag1[p],x); else { int mid=L+R>>1; if (l<=mid) modi1(p<<1,L,mid,l,r,x); if (r>mid) modi1(p<<1|1,mid+1,R,l,r,x); }}void modi2(int p,int L,int R,int l,int r,int x){ if (l<=L&&R<=r) tag2[p]=min(tag2[p],x); else { int mid=L+R>>1; if (l<=mid) modi2(p<<1,L,mid,l,r,x); if (r>mid) modi2(p<<1|1,mid+1,R,l,r,x); }}int get(int p,int L,int R,int x){ int ret=min(tag1[p],x+tag2[p]); if (L<R) { int mid=L+R>>1; if (x<=mid) ret=min(ret,get(p<<1,L,mid,x)); else ret=min(ret,get(p<<1|1,mid+1,R,x)); } return ret;}int main(){ int m=26,p; scanf("%s",s+1); n=strlen(s+1); for (int i=1;i<=n;i++) cnt[rank[i]=s[i]-'a'+1]++; for (int i=2;i<=m;i++) cnt[i]+=cnt[i-1]; for (int i=n;i;i--) sa[cnt[rank[i]]--]=i; for (int k=1;;k<<=1) { p=0; for (int i=n-k+1;i<=n;i++) f[++p]=i; for (int i=1;i<=n;i++) if (sa[i]>k) f[++p]=sa[i]-k; for (int i=1;i<=m;i++) cnt[i]=0; for (int i=1;i<=n;i++) cnt[rank[f[i]]]++; for (int i=2;i<=m;i++) cnt[i]+=cnt[i-1]; for (int i=n;i;i--) sa[cnt[rank[f[i]]]--]=f[i]; for (int i=1;i<=n;i++) f[i]=rank[i]; rank[sa[1]]=1; for (int i=2;i<=n;i++) if (f[sa[i]]==f[sa[i-1]]&&f[sa[i]+k]==f[sa[i-1]+k]) rank[sa[i]]=rank[sa[i-1]]; else rank[sa[i]]=rank[sa[i-1]]+1; m=rank[sa[n]]; if (m>=n) break; } for (int i=1;i<=n;i++) { height[rank[i]]=height[rank[i-1]]; if (height[rank[i]]) height[rank[i]]--; while (s[i+height[rank[i]]]==s[sa[rank[i]-1]+height[rank[i]]]) height[rank[i]]++; } init(1,1,n); for (int i=1;i<=n;i++) { p=max(height[rank[i]],height[rank[i]+1]); if (i+p<=n) { modi1(1,1,n,i,i+p,p+1); modi2(1,1,n,i+p,n,-i+1); } } for (int i=1;i<=n;i++) printf("%d\n",get(1,1,n,i));}
阅读全文
0 0
- bzoj1396 识别子串【解法一】
- bzoj1396 识别子串【解法二】
- bzoj1396: 识别子串
- bzoj1396
- 最长回文子串-解法一
- bzoj3277 串【解法一】
- 最长公共子串【动态规划解法】
- 最长回文子串的不同解法
- 最长回文子串解法详解
- hihocoder 最长回文子串简单解法
- 最长对称子串(动态规划解法)
- 最长回文子串的解法
- 回文串判定 解法一
- [BZOJ 1396] 识别子串
- bzoj 1396 识别子串
- 字符设备的子设备的识别方法一
- 最长不完全匹配子串频率计算-eaglet 的解法
- 最长公共子串问题的后缀数组解法
- 离散题目14--判断集合的对称性
- java复习--数据类型的转换,java运算符
- TCP 编程时的 flush() 问题
- IIS Express 启用目录浏览
- 分层开发
- bzoj1396 识别子串【解法一】
- SpringMVC 配置Jackson方法
- SharePreference的封装使用,让数据的本地缓存更简单
- [JavaEE] 关于JPA entity 重写equals()和hashcode()的说明
- Android之隐藏标题栏、状态栏
- 编程之美2.3 寻找发帖“水王”
- 洛谷 P2827 蚯蚓
- 数的读法
- 离散题目16--求自反闭包