zoukankan      html  css  js  c++  java
  • [后缀数组] Luogu P5028 Annihilate

    题目描述

    黑暗之主的蜈蚣几乎可以毁灭一切,因此小正方形陷入了苦战……

    小正方形现在需要减弱黑暗之主的攻击。

    一个黑暗之主的攻击可以用一个仅有小写字母的字符串表示。

    现在黑暗之主向小正方形发动了若干攻击,对于两个攻击,小正方形能选出它们最长的公共子串,并把这一段消除。

    现在小正方形想要知道,对于任意两个黑暗之主的攻击,它们的最长公共子串长度是多少,你能帮帮它吗?

    题解

    • 先把所有的字符串拼起来,每两个之间用个奇奇怪怪的字符隔出,然后就跑SA
    • 题目要求是要求最长公共字串,我们要找的是最长的,又因为ans是一段height的min,所以肯定找最近的
    • 于是,pre[i]不再维护位置了,维护最近一次出现的位置到当前的min(height)就行了

    代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #define N 2000010 
     5 #define M 60 
     6 using namespace std;
     7 int n,l,m=600,t[N],x[N],c[N],sa[N],bel[N],height[N],rank[N],pre[M],len[M],ans[M][M];
     8 char s[N];
     9 void get_SA()
    10 {
    11     l=len[n]+1;
    12     for (int i=1;i<=l;i++) c[x[i]=s[i]]++;
    13     for (int i=2;i<=m;i++) c[i]+=c[i-1];
    14     for (int i=l;i>=1;i--) sa[c[x[i]]--]=i;
    15     for (int k=1;k<=l;k<<=1)
    16     {
    17         int p=0;
    18         for (int i=l-k+1;i<=l;i++) t[++p]=i;
    19         for (int i=1;i<=l;i++) if (sa[i]>k) t[++p]=sa[i]-k;
    20         for (int i=1;i<=m;i++) c[i]=0;
    21         for (int i=1;i<=l;i++) c[x[i]]++;
    22         for (int i=2;i<=m;i++) c[i]+=c[i-1];
    23         for (int i=l;i>=1;i--) sa[c[x[t[i]]]--]=t[i],t[i]=0;
    24         swap(x,t);
    25         p=1,x[sa[1]]=1;
    26         for (int i=2;i<=l;i++) x[sa[i]]=(t[sa[i-1]]==t[sa[i]]&&t[sa[i-1]+k]==t[sa[i]+k])?p:++p; 
    27         if (p==l) break;
    28         m=p;
    29     }
    30     int k=0;
    31     for (int i=1;i<=l;i++) rank[sa[i]]=i;
    32     for (int i=1;i<=l;i++)  
    33     {
    34         if (rank[i]==1) continue;
    35         if (k) k--;
    36         int j=sa[rank[i]-1];
    37         while (j+k<=l&&i+k<=l&&s[i+k]==s[j+k]) k++;
    38         height[rank[i]]=k;
    39     }
    40 }
    41 int main()
    42 {
    43     scanf("%d",&n),len[0]=-1;
    44     for (int i=1;i<=n;i++)
    45     {
    46         char ch;
    47         while (!isalpha(ch=getchar()));
    48         for (len[i]=len[i-1]+1,s[++len[i]]=ch,bel[len[i]]=i;isalpha(ch=getchar());s[++len[i]]=ch,bel[len[i]]=i);
    49         s[len[i]+1]=300+i; 
    50     }
    51     get_SA();
    52     for (int i=2;i<=l;i++)
    53     {
    54         for (int j=1;j<=n;j++) pre[j]=min(pre[j],height[i]);
    55         int b=bel[sa[i]]; pre[bel[sa[i-1]]]=height[i];
    56         if (!b) continue;
    57         for (int j=1;j<=n;j++) ans[j][b]=ans[b][j]=max(ans[b][j],pre[j]);
    58     }
    59     for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) if (i!=j) printf("%d ",ans[i][j]); printf("
    "); } 
    60 }
  • 相关阅读:
    beacon帧字段结构最全总结(三)——VHT字段总结
    beacon帧字段结构最全总结(二)——HT字段总结
    [LeetCode]题53:Maximum Subarray
    [LeetCode]题15:3Sum
    dilated convolutions:扩张卷积
    python:assert
    [LeetCode]题1:two sum
    opencv3.0配置opencv_contrib
    python学习:数据类型
    python:字典嵌套列表
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11262089.html
Copyright © 2011-2022 走看看