【BZOJ】1535: [POI2005]Sza-Template
2015-11-22 13:28
323 查看
题意
给一个串\(s(1 \le |s| \le 500000)\),求一个最长的串,使得这个串能覆盖整个串(可以重叠)。分析
首先这个串肯定是前缀也肯定是后缀。题解
对串kmp后,建立\(fail\)树,则答案在根到\(n\)的路径上。假设当前串为\(a\),位置在\(i\),则所有出现了\(a\)的位置相邻两个的距离要小于等于\(|a|\),也就是在这个fail树中,\(i\)号点子树中相邻的两个距离要小于等于\(|a|\)。考虑从根dfs,每一次我们都会沿着其中一个孩子走,其它孩子都会去掉,那么我们就删掉其它孩子及其子树就行了!而由于下降的过程中距离是增大的,所以我们直接用一个链表维护最大值即可。#include <bits/stdc++.h> using namespace std; const int N=500005; int ihead , cnt, n, mx, pre , nxt , p , s , ok , ans; struct E { int next, to; }e ; void add(int x, int y) { e[++cnt]=(E){ihead[x], y}; ihead[x]=cnt; } void del(int x) { nxt[pre[x]]=nxt[x]; pre[nxt[x]]=pre[x]; mx=max(mx, nxt[x]-pre[x]); for(int i=ihead[x]; i; i=e[i].next) { del(e[i].to); } } void dfs(int x) { if(mx<=x) { ans=x; return; } int y=0; for(int i=ihead[x]; i; i=e[i].next) { if(ok[e[i].to]) { y=e[i].to; } else { del(e[i].to); } } if(y) { dfs(y); } } int main() { n=0; int c=getchar(), j=0; s[++n]=c; nxt =n+1; add(0, n); for(s[++n]=c=getchar(); c>='a' && c<='z'; s[++n]=c=getchar()) { for(; j && s[j+1]!=c; j=p[j]); if(s[j+1]==c) { ++j; } p =j; add(j, n); pre =n-1; nxt =n+1; } --n; nxt =0; for(int i=n; i; ok[i]=1, i=p[i]); mx=1; dfs(0); printf("%d\n", ans); return 0; }
相关文章推荐
- 机器学习实战笔记(1)机器学习基础
- 华为OJ中级题-查找两个字符串a,b中的最长公共子串
- linux 775和777权限有什么区别
- [LeetCode]Jump Game II
- gdb逆向调试
- ubuntu14.04完全卸载mysql
- mac 在 finder 当前 路径下 打开 terminal 的办法
- 架构的那些事2--安卓的奋进
- linux su和sudo命令的区别
- 数据类型输出
- 指令
- 【BZOJ】1532: [POI2005]Kos-Dicing
- web前端图表js选择-推荐highcharts
- [LeetCode]Longest Substring Without Repeating Characters
- 一些想法
- JS获取CSS样式(style/getComputedStyle/currentStyle)
- 【BZOJ】1524: [POI2006]Pal
- 进制之间的转换
- 优先级
- input标签placeholder属性IE8及以下版本的兼容性问题