日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

P4248-[AHOI2013]差异【SAM or SA】

發布時間:2023/12/3 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P4248-[AHOI2013]差异【SAM or SA】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/P4248


題目大意

TiT_iTi?表示后綴i~ni\sim nin
一個字符串求
∑i=1n∑j=inlen(Ti)+len(Tj)?2?lcp(Ti,Tj)\sum_{i=1}^n\sum_{j=i}^nlen(T_i)+len(T_j)-2*lcp(T_i,T_j)i=1n?j=in?len(Ti?)+len(Tj?)?2?lcp(Ti?,Tj?)


解題思路

有兩種做法,這里標程用的是SAMSAMSAM

SAMSAMSAM做法

這個式子和樹上路徑長度很像,順著這個思路,我們可以想到SAMSAMSAM上的ParentParentParent樹。

兩個后綴的lcplcplcp就是ParentParentParent樹上的LCALCALCA的節點代表的字符串,我們讓邊長為lenx?lenfailxlen_x-len_{fail_x}lenx??lenfailx??,然后答案就變為了樹上的每條路徑長度和。

那一條邊的貢獻就是(num?sizx)?sizx?len(num-siz_x)*siz_x*len(num?sizx?)?sizx??len
統計即可,時間復雜度O(n)O(n)O(n)

SASASA做法

我們先計算定值∑i=1n∑j=inlen(Ti)+len(Tj)\sum_{i=1}^n\sum_{j=i}^nlen(T_i)+len(T_j)i=1n?j=in?len(Ti?)+len(Tj?)
這里的定值就是n?(n?1)?(n+1)2\frac{n*(n-1)*(n+1)}{2}2n?(n?1)?(n+1)?

然后我們考慮如何計算LCPLCPLCP的和
heighti=LCP(i,i?1)height_i=LCP(i,i-1)heighti?=LCP(i,i?1)
我們有LCP(i,j)=min{heightk}(i<k≤j)LCP(i,j)=min\{height_k\}(i<k\leq j)LCP(i,j)=min{heightk?}(i<kj)
所以這里的答案就變為了∑i=2n∑j=inmin{heightk}(i≤k≤j)\sum_{i=2}^{n}\sum_{j=i}^nmin\{height_k\}(i\leq k\leq j)i=2n?j=in?min{heightk?}(ikj)
我們每個heightiheight_iheighti?的貢獻分開統計即可


codecodecode

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=2e6+10; struct node{ll to,next,w; }a[N]; ll n,tot,ls[N],ans,num,siz[N]; ll next[N][26],len[N],fail[N],cnt; char s[N]; void New_Point(ll x,ll v){next[x][v]=++cnt;len[cnt]=len[x]+1; } void addl(ll x,ll y,ll w){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w; } void Make_SAM(){ll now;now=cnt=1;for(ll i=1;i<=n;i++){ll val=s[i]-'a';New_Point(now,val);ll x=now,y;now=cnt;for(y=fail[x];y;y=fail[y])if(!next[y][val])next[y][val]=now;else{if(len[y]+1==len[next[y][val]])fail[now]=next[y][val];else{ll z=next[y][val];New_Point(y,val);fail[cnt]=fail[z];fail[z]=fail[now]=cnt;for(ll i=0;i<26;i++)next[cnt][i]=next[z][i];for(ll j=y;j;j=fail[j])if(next[j][val]==z)next[j][val]=cnt;}break;}siz[now]=1;if(!y) fail[now]=1;}for(ll i=2;i<=cnt;i++){num+=siz[i];addl(fail[i],i,len[i]-len[fail[i]]);} } void dfs(ll x){for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;dfs(y);ans+=siz[y]*(num-siz[y])*a[i].w;siz[x]+=siz[y];} } int main() {scanf("%s",s+1);n=strlen(s+1);Make_SAM();dfs(1);printf("%lld",ans); }

總結

以上是生活随笔為你收集整理的P4248-[AHOI2013]差异【SAM or SA】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。