uval1297 Palindrome 后缀数组求最长回文字串,lcp,rmq
2015-09-18 13:55
357 查看
#include<iostream> #include<cstring> #include<cstdio> #include<ostream> #include<istream> #include<algorithm> #include<queue> #include<string> #include<cmath> #include<set> #include<map> #include<stack> #include<vector> #define fi first #define se second #define ll long long #define pii pair<int,int> #define inf (1<<30) #define eps 1e-8 #define pb push_back using namespace std; const int maxn=110005; char str[maxn]; int s[maxn]; int n; int dp[maxn][25]; int N=25; int t1[maxn],t2[maxn],c[maxn]; int sa[maxn],ra[maxn],height[maxn]; void buildSa(int s[],int n,int m)//最大值小于m { int i,j,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=s[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(j=1;j<=n;j<<=1) { p=0; for(i=n-j;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; if(p>=n)break; m=p; } } void getHeight(int s[],int n) { int i,j,k=0; for(i=0;i<=n;i++)ra[sa[i]]=i; for(i=0;i<n;i++) { if(k)k--; j=sa[ra[i]-1]; while(s[i+k]==s[j+k])k++; height[ra[i]]=k; } } int lcp(int a,int b) { a=ra[a],b=ra[b]; if(a>b) swap(a,b); a++; int k=log2(b-a+1); return min(dp[a][k],dp[b-(1<<k)+1][k]); } int main() { while(~scanf("%s",str)) { n=strlen(str); str ='#'; for(int i=n+1,j=n-1;j>=0;i++,j--) str[i]=str[j]; int nn=n*2+1; str[nn]='\0'; for(int i=0;i<=nn;i++) s[i]=str[i]; buildSa(s,nn+1,128); getHeight(s,nn); for(int i=1;i<=nn;i++) dp[i][0]=height[i]; for(int j=1;j<N;j++) { for(int i=1;i<=nn;i++) { if(i+(1<<j)-1<=nn) { dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } } } int len=0; int st; for(int i=0;i<n;i++) { int tmp=lcp(i+1,nn-i);//以i为中心,长度为奇 if(tmp*2+1>len) { len=tmp*2+1; st=i-tmp; } else if(tmp*2+1==len) { st=min(st,i-tmp); } tmp=lcp(i,nn-i);//长度为偶 if(tmp*2>len) { len=tmp*2; st=i-tmp; } else if(tmp*2==len) { st=min(st,i-tmp); } } for(int i=st,j=0;j<len;i++,j++) putchar(str[i]); puts(""); } return 0; }
相关文章推荐
- JS判断移动设备的终端类型(浏览器UserAgent)
- Java基础の乱弹琴二:break关键字
- 时间序列分析
- Hibernate – fetching strategies examples
- js函数参数设置默认值的一种变通实现方法
- 快排,动态内存
- git上传完整实例
- Android Studio插件给你带来开发便利
- Ubuntu 14.04 Storm(单机版)安装
- 手机淘宝中的那些Web技术-使用了类似PhoneGap的实现
- sessionID和cookie
- uva 400
- PHP学习笔记一
- android5.0开发之解决灭屏来日程只有声音没有亮屏
- c语言中 ++i 和 i++ 问题!
- The Castle(USACO 2.1.1)
- 一道面试题Lintcode196-Find the Missing Number
- 百度翻译API请求
- OpenCV for Ios 学习笔记(9)-用OPENGL渲染AR场景2
- css3新属性placeholder兼容ie7/ie8