URAL - 1297 后缀数组的做法 LCP应用
题意:求最长回文子串
这种有专门的O(n)套板子算法,但作为练习还是用后缀数组来解吧
只需把相同的另一个串反接(中间用一个足够小且未出现的字符衔接),然后枚举回文串的中点,不断求解该点往前和往后计算的\(LCP\)即可
发现模板有个BUG改好了
有个值得注意的地方是回文长度奇偶枚举时的端点选择问题,具体直接看栗子
abcccd
奇数枚举时应该是abcccd#dcccba
偶数枚举时应该是abcccd#dcccba
两个子串枚举首端与#的距离相等或相差一,列出式子就是当奇数端枚举\(i\)时,另一子串始端为\(2n+2-i\),偶数端为\(2n+3-i\)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define iin(a) scanf("%d",&a)
#define lin(a) scanf("%lld",&a)
#define din(a) scanf("%lf",&a)
#define s0(a) scanf("%s",a)
#define s1(a) scanf("%s",a+1)
#define print(a) printf("%lld",(ll)a)
#define enter putchar('\n')
#define blank putchar(' ')
#define println(a) printf("%lld\n",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int maxn = 1e5+11;
const int oo = 0x3f3f3f3f;
const double eps = 1e-7;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
char str[maxn];int n;
struct SA{
int Rank[maxn],sa[maxn],tsa[maxn],A[maxn],B[maxn];
int cntA[maxn],cntB[maxn];
int height[maxn],best[maxn][30],n;
void get(int nn){
n=nn;
rep(i,0,666) cntA[i]=0;
rep(i,1,n) cntA[str[i]]++;
rep(i,1,666) cntA[i]+=cntA[i-1];
rrep(i,n,1) sa[cntA[str[i]]--]=i;
Rank[sa[1]]=1;
rep(i,2,n){
if(str[sa[i]]==str[sa[i-1]]){
Rank[sa[i]]=Rank[sa[i-1]];
}else{
Rank[sa[i]]=1+Rank[sa[i-1]];
}
}
for(int l=1;Rank[sa[n]]<n;l<<=1){
rep(i,1,n) cntA[i]=cntB[i]=0;
rep(i,1,n) cntA[A[i]=Rank[i]]++;
rep(i,1,n) cntB[B[i]=(i+l<=n?Rank[i+l]:0)]++;
rep(i,1,n) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
rrep(i,n,1) tsa[cntB[B[i]]--]=i;
rrep(i,n,1) sa[cntA[A[tsa[i]]]--]=tsa[i];
Rank[sa[1]]=1;
rep(i,2,n){
bool flag=A[sa[i]]==A[sa[i-1]]&&B[sa[i]]==B[sa[i-1]];
flag=!flag;
Rank[sa[i]]=Rank[sa[i-1]]+flag;
}
}
}
void ht(){
int j=0;
rep(i,1,n){
if(j) j--;
while(str[i+j]==str[sa[Rank[i]-1]+j]) j++;
height[Rank[i]]=j;
}
}
void rmq(){
rep(i,1,n) best[i][0]=height[i];
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j+(1<<i)-1<=n;j++){
best[j][i]=min(best[j][i-1],best[j+(1<<(i-1))][i-1]);
}
}
}
int query(int l,int r){
if(l==r)return -oo;
if(l>r)swap(l,r);
l++;
int k=log2(r-l+1);
return min(best[l][k],best[r-(1<<k)+1][k]);
}
}sa;
char sstr[maxn];
int main(){
while(~s1(str)){
n=strlen(str+1);
rep(i,1,n+1) sstr[i]=str[i];
reverse(sstr+1,sstr+1+n);
str[n+1]=1;str[n+2]=0;
strcat(str+1,sstr+1);
str[2*n+2]=0;
int nn=2*n+1;
sa.get(nn);
sa.ht();
sa.rmq();
int ans=1,pos=1;
rep(i,1,n){
if(1){
int odd=sa.query(sa.Rank[i],sa.Rank[2*n+2-i]);
if(ans<2*odd-1)ans=2*odd-1,pos=i-odd+1;
}
int even=sa.query(sa.Rank[i],sa.Rank[2*n+3-i]);
if(ans<2*even)ans=2*even,pos=i-even;
}
// cout<<ans<<endl;
str[ans+pos]=0;printf("%s\n",str+pos);
memset(str,0,sizeof str);
memset(sstr,0,sizeof sstr);
}
return 0;
}
URAL - 1297 后缀数组的做法 LCP应用的更多相关文章
- ural 1297(后缀数组+RMQ)
题意:就是让你求一个字符串中的最长回文,如果有多个长度相等的最长回文,那就输出第一个最长回文. 思路:这是后缀数组的一种常见的应用,首先把原始字符串倒转过来,然后接在原始字符串的后面,中间用一个不可能 ...
- URAL 1297 后缀数组:求最长回文子串
思路:这题下午搞了然后一直WA,后面就看了Discuss,里面有个数组:ABCDEFDCBA,这个我输出ABCD,所以错了. 然后才知道自己写的后缀数组对这个回文子串有bug,然后就不知道怎么改了. ...
- ural 1297 后缀数组 最长回文子串
https://vjudge.net/problem/URAL-1297 题意: 给出一个字符串求最长回文子串 代码: //论文题,把字符串反过来复制一遍到后边,中间用一个没出现的字符隔开,然后就是枚 ...
- URAL 1297 后缀数组+线段树
思路: 论文题--*n 倒过来接上 分奇偶讨论 求LCP 搞棵线段树即可 //By SiriusRen #include <cstdio> #include <cstring> ...
- 后缀数组 hash求LCP BZOJ 4310: 跳蚤
后缀数组的题博客里没放进去过..所以挖了一题写写 充实下博客 顺便留作板子.. 一个字符串S中 内容不同的子串 有 sigma{n-sa[i]+1-h[i]} (噢 这里的h[]就是大家熟知的he ...
- 后缀数组入门(二)——Height数组与LCP
前言 看这篇博客前,先去了解一下后缀数组的基本操作吧:后缀数组入门(一)--后缀排序. 这篇博客的内容,主要建立于后缀排序的基础之上,进一步研究一个\(Height\)数组以及如何求\(LCP\). ...
- Ural1297 Palindrome(后缀数组)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12406 [题意] 求最长回文子串. [思路] 将字符串 ...
- ural 1297. Palindrome
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1297 求最长回文子串 典型的后缀数组的入门题目,但是可以用更简单的方法解决,毕竟数据量比 ...
- 【BZOJ4566】找相同字符(后缀数组)
[BZOJ4566]找相同字符(后缀数组) 题面 BZOJ 题解 后缀数组的做法,应该不是很难想 首先看到两个不同的串,当然是接在一起求\(SA,height\) 那么,考虑一下暴力 在两个串各枚举一 ...
随机推荐
- grid search
sklearn.metrics.make_scorer(score_func, greater_is_better=True, needs_proba=False, needs_threshold=F ...
- Java 线程不安全问题分析
当多个线程并发访问同一个资源对象时,可能会出现线程不安全的问题 public class Method implements Runnable { private static int num=50; ...
- android 优秀图表库之MPAndroidChart
MPAndroidChart 1.在项目当中很多时候要对数据进行分析就要用到图表,在gitHub上有很多优秀的图表开源库,这里就简单介绍一下MPAndroidChart. 他可以实现图表的拖动,3D, ...
- Android getDimension,getDimensionPixelOffset,getDimensionPixelSize
1.例如在onMeasure(int , int)方法中可能要获取自定义属性的值.如: TypedArray a = context.obtainStyledAttributes(attrs, R.s ...
- C# enum 枚举 反射
枚举遍历 public enum EMyType { [System.ComponentModel.Description("A类型")] TypeA = 1, [System.C ...
- [Algorithm]图
一.图的算法 邻接矩阵表示的数据结构 1 #define INFINITY INT_MAX // 无穷大 2 #define MAX_VERTEX_NUM 20 // 限制顶点最大数值为20个 3 # ...
- Delphi XE8中开发DataSnap程序常见问题和解决方法 (二)想对DBExpress的TSQLDataSet写对数据库操作的SQL语句出错了!
当我们搞定DataSnap后,我们进入客户端程序开发阶段了,我们建立了客户端模块后,打算按照刚才开发服务器的步骤开发客户端程序,随后加入了DBExpress的TSQLDataSet,设定数据库连接后, ...
- linux联网配置(更新)
重启网络配置:service network restart: 常见问题: linux 虚拟机ifconfig 显示eth1 文件ifcfg-eth0中device为eth0的问题 为什么eth0 ...
- Educational Codeforces Round 62 (Rated for Div. 2)E(染色DP,构造,思维,组合数学)
#include<bits/stdc++.h>using namespace std;const long long mod=998244353;long long f[200007][2 ...
- 文件操作 - 整体操作&文件搜索
文件操作 - 整体操作 1.touch 作用:创建普通文件 格式:touch file1 [file2] 2.cp 作用:拷贝文件 格式:cp 源文件 目标文件 3.rm 作用:删除文件 格式:rm ...