洛谷P4094 TJOI2016 字串

2022-08-11 07:54:10 字數 1549 閱讀 5048

portal

給出乙個字串\(s(|s|\leq10^5)\)和\(m\)次詢問,每次詢問子串\(s[x_1..x_2]\)的所有子串和\(s[y_1..y_2]\)的最長公共字首長度的最大值。

字尾陣列+二分答案+主席樹。

易知\(s[x_1..x_2]\)的所有子串可以視為\(s[x_1..x_2]\)的所有字尾。那麼可以得到:

\[ ans=max\ \quad (i\in [x_1,x_2])$$ $lcp(i,j)$表示字尾$i$與字尾$j$的最長公共字首長度。用字尾陣列可以在$o(nm)$內搞定。

考慮二分答案$ans\in [0,min(x_2-i+1,y_2-y_1+1)]$,二分結果為$len$。由於$lcp(i,y_1)$相當於一段區間的最小值,那麼$rnk[i]$離$rnk[y_1]$越遠就越小。那麼我們可以再次二分來找到乙個區間$[fr,to]$,$\forall i\in [fr,to]$,有$lcp(sa[i],y_1)\geq len$。那麼檢查是否有$sa[i]\in [x_1,x_2-len+1]$,若有則說明$len$合法,擴大$len$;否則不合法,縮小$len$。

於是我們要做的就是求$sa$的某個區間內是否有某個數在某個範圍內。對$sa$建立$n$棵線段樹,第$i$棵的第$j$位為$1$表示在$sa[1..i]$中有$j$。詢問時查詢兩棵線段樹的差即可。

> 時間複雜度$o((n+m)logn)$。

##code

```cpp

//[tjoi2016]字串

#include #include inline int read()

memcpy(rnk,rnk1,sizeof rnk1);

}for(int i=1,k=0;i<=n;i++)

if(k) k--;

while(s[i+k]==s[sa[rnk[i]-1]+k]) k++;

h[rnk[i]]=k;

}lg2[1]=0; for(int i=2;i<=n;i++) lg2[i]=lg2[i>>1]+1;

for(int i=1;i<=n;i++) st[i][0]=h[i];

for(int k=1;(1i++;

int t=lg2[j-i+1];

return min(st[i][t],st[j-(1<>1;

if(x<=mid) ins(nd[p].chl,l0,mid,x);

else ins(nd[p].chr,mid+1,r0,x);

update(p);

}int optl,optr;

int qres;

void query(int p1,int p2,int l0,int r0)

int mid=l0+r0>>1;

if(optl<=mid) query(nd[p1].chl,nd[p2].chl,l0,mid);

if(mid>1;

if(lcp(sa[mid],y1)>1;

if(lcp(y1,sa[mid])0;

}int main()

printf("%d\n",r);

}return 0;

}```\]

洛谷P3761 TJOI2017 城市

從加里敦大學城市規劃專業畢業的小明來到了乙個地區城市規劃局工作。這個地區一共有ri座城市,1條高速公路,保證了任意兩運城市之間都可以通過高速公路相互可達,但是通過一條高速公路需要收取一定的交通費用。小明對這個地區深入研究後,覺得這個地區的交通費用太貴。小明想徹底改造這個地區,但是由於上司給他的資源有...

洛谷P3976 TJOI2015 旅遊

為了提高智商,zjy 準備去往乙個新世界去旅遊。這個世界的城市布局像一棵樹,每兩座城市之間只有一條路徑可以互達。每座城市都有一種寶石,有一定的 zjy 為了賺取最高利益,她會選擇從 a 城市 再轉手賣到 b 城市。由於zjy買寶石時經常賣萌,因而凡是 zjy 路過的城市,這座城市的寶石 會 讓我們來...

洛谷P3758 TJOI2017 可樂

加里敦星球的人們特別喜歡喝可樂。因而,他們的敵對星球研發出了乙個可樂機械人,並且放在了加里敦星球的1號城市上。這個可樂機械人有三種行為 停在原地,去下乙個相鄰的城市,自爆。它每一秒都會隨機觸發一種行為。現 在給加里敦星球城市圖,在第0秒時可樂機械人在1號城市,問經過了t秒,可樂機械人的行為方案數是多...