现在的位置: 首页 > 综合 > 正文

【dp/后缀树】最长回文串、最长重复回文串、最长非重复回文串。。

2018年04月12日 ⁄ 综合 ⁄ 共 907字 ⁄ 字号 评论关闭

回文串DP:

首先在原string中加‘*’ 

k = i + min( mr - i,  len[2*mi - i]/2 ) +1 :    中间一项t为以mi为中心与i对称的点j对应的最长回文串(sj)
点mi对应回文串覆盖范围内的 半长度。 

k=i+t+1,直接跳到该位置进行匹配


#include <iostream>
#include <stdio.h>
using namespace std;
char str[1000001];
char buf[2000002]; 
int len[2000002];

int main(){
  int n; cin>>n;
  for(int casei=0; casei<n; casei++){
    scanf("%s", str);
    if(!str[0]) {
      cout<<0<<endl;
      continue;
    }
    for(int i=0, j=0; ; i++, j++){
      if(!str[i]) {buf[j-1]=0; break;}
      buf[j]=str[i];
      buf[++j]='*';
    }

    len[0]=1;
    int mr=0, mi=0; 
    for(int i=1; buf[i]; i++){
      int k;
      if(mr>=i){
        int j=2*mi-i;
        // k=i+len[j]/2+1;//error
        int t = min( len[j]/2, mr-i );  //i+j=2*mi, so j-(2*mi-mr) = mr-i 
        k = i + t + 1;
        // cout<<i<<":"<<j<<":"<<len[j]<<":"<<k<<endl;
      }
      else
        k=i+1;
    
      // k从i回文串右边起点开始,匹配对应左边
      for(; buf[k]; k++){
        if(2*i-k<0 || buf[2*i-k]!=buf[k]) break;
      }
      k--;  //k对应i回文串的最右端下标
      len[i]=k-(2*i-k)+1;
      if(k>mr) mr=k, mi=i;
    }
    int ml=0, mx=-1;
    for(int i=0; buf[i]; i++){
      int l=len[i];
      if(buf[i]=='*') l=(1+l)/4*2;
      else l=(1+(1+l)/2)/2*2-1;
      if(ml<l) ml=l, mx=i;
    }
    cout<<ml<<endl;
  }
  return 0;
}

抱歉!评论已关闭.