• Ural 1297 Palindrome(后缀数组+最长回文子串)


    https://vjudge.net/problem/URAL-1297

    题意:

    求最长回文子串。

    思路:

    先将整个字符串反过来写在原字符串后面,中间需要用特殊字符隔开,那么只需要某两个后缀的最长公共前缀。当然,这两个后缀不是让你随便选的,我们需要先确定回文串的中心(那么这儿就需要注意一下奇偶数的情况了,具体可以看一下代码),确定了中心之后,在后面的逆串中,我们也要找到这个中心点的位置,要求的是这两个后缀的公共前缀。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 #include<set>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef pair<int,int> pll;
     14 const int INF = 0x3f3f3f3f;
     15 const int maxn=2000+5;
     16 
     17 int n;
     18 char s[maxn];
     19 int sa[maxn],t[maxn],t2[maxn],c[maxn];
     20 int Rank[maxn],height[maxn];
     21 int d[maxn][30];
     22 
     23 void build_sa(int m)
     24 {
     25     int *x=t,*y=t2;
     26     //基数排序
     27     for(int i=0;i<m;i++)    c[i]=0;
     28     for(int i=0;i<n;i++)    c[x[i]=s[i]]++;
     29     for(int i=1;i<m;i++)    c[i]+=c[i-1];
     30     for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
     31     for(int k=1;k<=n;k<<=1)
     32     {
     33         int p=0;
     34         //直接利用sa数组排序第二关键字
     35         for(int i=n-k;i<n;i++)  y[p++]=i;
     36         for(int i=0;i<n;i++)    if(sa[i]>=k)    y[p++]=sa[i]-k;
     37         //基数排序第一关键字
     38         for(int i=0;i<m;i++)    c[i]=0;
     39         for(int i=0;i<n;i++)    c[x[y[i]]]++;
     40         for(int i=1;i<m;i++)    c[i]+=c[i-1];
     41         for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
     42         //根据sa和y计算新的x数组
     43         swap(x,y);
     44         p=1;
     45         x[sa[0]]=0;
     46         for(int i=1;i<n;i++)
     47             x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
     48         if(p>=n)
     49             break;
     50         m=p;                //下次基数排序的最大值
     51     }
     52 }
     53 
     54 void getHeight(int n)
     55 {
     56     int i,j,k=0;
     57     for(i=1;i<=n;i++)  Rank[sa[i]]=i;
     58     for(i=0;i<n;i++)
     59     {
     60         if(k)  k--;
     61         int j=sa[Rank[i]-1];
     62         while(s[i+k]==s[j+k])  k++;
     63         height[Rank[i]]=k;
     64     }
     65 }
     66 
     67 void RMQ(int n)
     68 {
     69     for(int i=1;i<=n;i++)  d[i-1][0]=height[i];
     70     for(int j=1;(1<<j)<=n;j++)
     71         for(int i=0;i+(1<<j)-1<n;i++)
     72         d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
     73 }
     74 
     75 int query(int L, int R)
     76 {
     77     int k=0;
     78     while((1<<(k+1))<=R-L+1)  k++;
     79     return min(d[L][k],d[R-(1<<k)+1][k]);
     80 }
     81 
     82 int LCP(int a, int b)
     83 {
     84     int x=Rank[a],y=Rank[b];
     85     if(x>y)  swap(x,y);
     86     x--; y--;
     87     if(y<0)  return 0;
     88     return query(x+1,y);
     89 }
     90 
     91 int main()
     92 {
     93     //freopen("in.txt","r",stdin);
     94     while(~scanf("%s",s))
     95     {
     96         int len = strlen(s);
     97         s[len]='1';
     98         for(int i=0;i<len;i++) s[i+len+1]=s[len-1-i];
     99         s[2*len+1]='0';  //这儿后面的数要加的不一样,一开始两个都加了'0'...
    100         n=2*len+2;
    101         build_sa(128);
    102         getHeight(n-1);
    103         RMQ(n-1);
    104         int ans=0, tmp, start;
    105         for(int i=0;i<len;i++)
    106         {
    107             tmp=LCP(i,n-i-2);  //长度为奇数的情况
    108             if(2*tmp-1>ans)
    109             {
    110                 ans=2*tmp-1;
    111                 start=i-tmp+1;
    112             }
    113             tmp=LCP(i,n-i-1);  //长度为偶数的情况
    114             if(2*tmp>ans)
    115             {
    116                 ans=2*tmp;
    117                 start=i-tmp;
    118             }
    119         }
    120         for(int i=start;i<start+ans;i++)
    121             printf("%c",s[i]);
    122         printf("
    ");
    123     }
    124     return 0;
    125 }
  • 相关阅读:
    离线数仓 建模、表的类型分类
    获取每个部门中当前员工薪水最高的相关信息
    dwd层 维度退化 的作用
    单例模式懒汉式
    反汇编命令使用
    RabbitMQ实战高级特性
    初步理解MySQL的gap锁
    【java并发系列】Controller是线程安全吗_ 安全方式如何
    mysql_14_count(*)为什么这么慢
    MySQL 通过Docker搭建主从同步
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7580290.html
Copyright © 2020-2023  润新知