題意:
問給出的串中連續重複的子串的最長的長度
思路:
先將字尾陣列和高度陣列先求出來,分別為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...
字尾樹 字尾陣列
在字串處理當中,字尾樹和字尾陣列都是非常有力的工具,其中字尾樹大家了解得比較多,關於字尾陣列則很少見於國內的資料。其實字尾陣列是字尾樹的乙個非 常精巧的替代品,它比字尾樹容易程式設計實現,能夠實現字尾樹的很多功能而時間複雜度也不太遜色,並且,它比字尾樹所占用的空間小很多。可以說,在資訊學競賽 中字尾...