最长回文子串 后缀数组

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rank rk
using namespace std;

typedef long long LL;

const int maxn = 2e5+10, M = 300;
// sa[1-n] -> 0->n-1;
int sa[maxn], rank[maxn], height[maxn];

int wa[maxn], wb[maxn], wv[maxn], cnt[maxn];
void SA(int *r, int n, int m) {
    int *x = wa, *y = wb;
    for(int i = 0; i < m; i++) cnt[i] = 0;
    for(int i = 0; i < n; i++) cnt[x[i] = r[i]]++;
    for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
    for(int i = n - 1; i >= 0; i--) sa[--cnt[x[i]]] = i;
    for(int j = 1; j < n; j <<= 1) {
        int p = 0;
        for(int i = n - j; i < n; i++) y[p++] = i;
        for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        for(int i = 0; i < n; i++) wv[i] = x[y[i]];
        for(int i = 0; i < m; i++) cnt[i] = 0;
        for(int i = 0; i < n; i++) cnt[wv[i]]++;
        for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
        for(int i = n - 1; i >= 0; i--) sa[--cnt[wv[i]]] = y[i];
        swap(x, y);
        p = 1; x[sa[0]] = 0;
        for(int 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 calcHeight(int *r, int n) {
    int i, j, k;
    for(i = j = k = 0; i < n; height[rank[i++]] = k)
        for(k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++);
}
int n, s[maxn];
char str[maxn];
int lg[maxn];
int st[maxn][20];
void make_ST(){
     for(int i=n;i>=1;i--){
         st[i][0]=height[i];
         for(int j=1;i+(1<<j-1)-1<=n;j++){
             st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
         }
     }
}
int main() {
    string str;
    for(int i=2;i<maxn;i++){lg[i]=lg[i>>1]+1;}
    while(cin>>str){
        int l=str.size();
        string ss=str; reverse(ss.begin(),ss.end());
        str=str+'#'+ss;
        n = str.size();
        for(int i = 0; i < n; i++) s[i] = str[i]; s[n] = 0;
        SA(s, n + 1, M);
        for(int i = 0; i <= n; i++) rank[sa[i]] = i;
        calcHeight(s, n);
        make_ST();
        int ans=0;
        for(int i=0;i<l;i++){
             int lll,rrr;
             lll=min(rank[i],rank[2*l-i])+1;
             rrr=max(rank[i],rank[2*l-i]);
             int d=lg[rrr-lll+1];
             ans=max(ans,min(st[lll][d],st[rrr-(1<<d)+1][d])*2-1);
             lll=min(rank[i+1],rank[2*l-i])+1;
             rrr=max(rank[i+1],rank[2*l-i]);
             d=lg[rrr-lll+1];
             ans=max(ans,min(st[lll][d],st[rrr-(1<<d)+1][d])*2);
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/Andromeda-Galaxy/p/10883209.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值