字尾陣列 RMQ SPOJ 687

2021-08-07 02:06:15 字數 1789 閱讀 5565

題意:

問給出的串中連續重複的子串的最長的長度

思路:

先將字尾陣列和高度陣列先求出來,分別為sa和lcp陣列。

然後用rmq的st演算法將從位置i和j開始的字尾的最長公共字首求出來,這個還好理解把,對與排名第一的字尾,它的高度陣列為與排名第二的字尾的最長公共字首,依次類推,比如到第四個,前四個分別為5,3,0,2;那麼第乙個與第三個的公共字首就為0,以第二個為媒介,第二個與第乙個的最長為5,第二個與第三個為0,那麼第乙個與第三個為0,與3後面的全為0,所以st求最小即可,然後就是列舉要重複的串的長度。

#include 

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int inf=0x3f3f3f3f;

const

int maxn=50010;

int wa[maxn],wb[maxn],wv[maxn],ww[maxn];

int sa[maxn],lcp[maxn],rank[maxn],rank1[maxn],dp[maxn][20];

char str[maxn];

int nn;

inline

bool cmp(int *r,int a,int b,int len)

void construct_sa(int n,int m)

for(i=0;i0;

for(i=0;ifor(i=1;i1];

for(i=n-1;i>=0;i--) sa[--ww[wv[i]]]=y[i];

for(t=x,x=y,y=t,x[sa[0]]=0,p=i=1;i1],sa[i],j)?p-1:p++;

} } void construct_lcp(int n)

} void rmq_init(int n)

} } int rmq(int le,int ri)

int main()

construct_sa(nn,100);

construct_lcp(nn);

rmq_init(nn);

int ans=0,sum;

for(int len=1;len//列舉重複的串的長度

for(int i=0;i+len//這裡為什麼直接加len就行,是因為

int t=rmq(i,i+len);//找i和i+len的最長字首

sum=t/len+1;//字首能拼成的長度為len的個數加上i到i+len的乙個

int pos=i-(len-t%len);//這個串的長度如果還有富裕,那麼看看前面是否新增幾個字元可以將重複次數在+1;

if(pos>=0&&t%len!=0) if(rmq(pos,pos+len)>=(len-t%len)) sum++;//這個判斷就是你缺幾個字元,如果從pos開始把這幾個

//字元填上了,那麼就可以在組成乙個

if(sum>ans) ans=sum;

} }

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

// for(int i=0;i<=nn;i++) coutreturn

0;

}

spoj687(字尾陣列)

題意 給一串字元,需要你求這一串字元中有連續重複的字元的重複次數.思路 這是和poj3693一種型別的題目.這裡是詳細解答 注意 還需注意的地方,我一直圖方便,再求lcp值時,總是從height值的起點到終點,其實應該是起點 1 include include includeusing namesp...

SPOJ 687 REPEATS(字尾陣列)

題意 求重複次數最多的連續重複子串的長度 題解 一樣的思路,列舉重複長度為l,就有rk pos rk pos rk pos 和rk p os l rk pos l rk pos l 這兩個串,pos為列舉的l的倍數,即rk k l rk k l rk k l 和rk k 1 l rk k 1 l r...

字尾樹 字尾陣列

在字串處理當中,字尾樹和字尾陣列都是非常有力的工具,其中字尾樹大家了解得比較多,關於字尾陣列則很少見於國內的資料。其實字尾陣列是字尾樹的乙個非 常精巧的替代品,它比字尾樹容易程式設計實現,能夠實現字尾樹的很多功能而時間複雜度也不太遜色,並且,它比字尾樹所占用的空間小很多。可以說,在資訊學競賽 中字尾...