Annihilate(SA)
生活随笔
收集整理的這篇文章主要介紹了
Annihilate(SA)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
黑暗之主的蜈蚣幾乎可以毀滅一切,因此小正方形陷入了苦戰……
小正方形現在需要減弱黑暗之主的攻擊。
一個黑暗之主的攻擊可以用一個僅有小寫字母的字符串表示。
現在黑暗之主向小正方形發動了若干攻擊,對于兩個攻擊,小正方形能選出它們最長的公共子串,并把這一段消除。
現在小正方形想要知道,對于任意兩個黑暗之主的攻擊,它們的最長公共子串長度是多少,你能幫幫它嗎?
題解
我是個**,字符集會隨著SA往后進行越來越大,數組開小調了倆小時。。
用SAM是板子,但它卡空間,所以把它接起來跑一邊SA。
我們按照字典序掃描所有后綴,維護一個數組,表示在當前位置到之前x個串的LCS,每次O(n)更新一遍。
代碼
#include<iostream> #include<cstdio> #define N 2100002 using namespace std; char s[N]; int rnk[N],y[N],sa[N],n,x,ji[N],m,tong[N],pre[52],height[N],ans[52][52],tot; inline void init(int x){char c=getchar();while(!isalpha(c))c=getchar();while(isalpha(c))s[++n]=c,ji[n]=x,c=getchar(); } inline void qsort(){for(int i=0;i<=m;++i)tong[i]=0;for(int i=1;i<=n;++i)tong[rnk[i]]++;for(int i=1;i<=m;++i)tong[i]+=tong[i-1];for(int i=n;i>=1;--i)sa[tong[rnk[y[i]]]--]=y[i]; } inline void SA(){for(int i=1;i<=n;++i)rnk[i]=s[i],y[i]=i;m=200;qsort();for(int w=1,p;p<n;m=p,w<<=1){p=0;for(int i=n-w+1;i<=n;++i)y[++p]=i;for(int i=1;i<=n;++i)if(sa[i]>w)y[++p]=sa[i]-w;qsort();swap(rnk,y);rnk[sa[1]]=p=1;for(int i=2;i<=n;++i)rnk[sa[i]]=((y[sa[i-1]]==y[sa[i]])&&(y[sa[i-1]+w]==y[sa[i]+w]))?p:++p;}for(int i=1;i<=n;++i){if(rnk[i]==1)continue;int j=max(0,height[rnk[i-1]]-1);while(s[i+j]==s[sa[rnk[i]-1]+j])j++;height[rnk[i]]=j;}for(int i=1;i<=n;++i){for(int j=1;j<=tot;++j)pre[j]=min(pre[j],height[i]);pre[ji[sa[i-1]]]=max(pre[ji[sa[i-1]]],height[i]);for(int j=1;j<=tot;++j)ans[ji[sa[i]]][j]=ans[j][ji[sa[i]]]=max(ans[j][ji[sa[i]]],pre[j]);} } int main(){scanf("%d",&tot);for(int i=1;i<=tot;++i){init(i);s[++n]=i;}SA();for(int i=1;i<=tot;++i){for(int j=1;j<=tot;++j)if(i!=j)printf("%d ",ans[i][j]);puts("");}return 0; }?
轉載于:https://www.cnblogs.com/ZH-comld/p/10189133.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Annihilate(SA)的全部內容,希望文章能夠幫你解決所遇到的問題。