Jzoj2921 NOI2012模擬題 字串識別

2021-08-08 13:16:18 字數 1551 閱讀 5514

題意:給乙個字串,對於每個位置i,求出最短滿足的子串[l,r]使得i∈[l,r]且這個子串只出現一次,輸出這個子串的長度

神(shui)題,ac後看了下別人的code發現全都是字尾陣列(難看)

可能是因為我太弱了所以只想到sam的演算法

做法:建立sam,求出parent樹,預處理倍增,讓後就可以o(lg n)查詢乙個字串的出現次數了

接下來,我們對於每個l∈[1,n],我們求出乙個最小的r使得[l,r]在整個串裡面只出現一次

那麼對於每個點i,ans[i]有兩種情況:

1.i被乙個最短的區間[lj,rj]覆蓋,那麼我們可以

把這些l,r區間按長度從大到小排序,並且用線段樹區間覆蓋

2.有可能是乙個區間[lj,rj](rj

對於這種情況,我們把所有區間按r排序,對於i,我們用二分找到最大的j使得rj

兩種情況取較小就可以了

**很長很醜,跑的也很慢。。。。

#include#include#include#define n 1000010

#define f f[0]

using namespace std;

struct pr r[n];

int f[20][n],s[n][26],mx[n],sz[n],d[n],m[n],n;

int v[n],r[n],m=1,cnt=1,last=1,a[n],pos[n],t[n<<2];

char str[n];

inline bool c1(pr a,pr b)

inline int extend(char c,int& o)

}inline void build()

}int gsz(int l,int r)

return sz[x];

}void cover(int l,int r,int x,int l,int r,int k)

if(t[x])

int mid=l+r>>1;

if(l<=mid) cover(l,mid,x<<1,l,r,k);

if(mid>1;

if(p<=mid) return gcover(l,mid,x<<1,p);

else return gcover(mid+1,r,x<<1|1,p);

}int main();

if(++l>r) ++r;

} sort(r+1,r+1+n,c2); t[1]=n;

for(int i=1;i<=n;++i)

if(r[i].r<=n) cover(1,n,1,r[i].l,r[i].r,r[i].r-r[i].l+1);

for(int i=1;i<=n;++i)

a[i]=gcover(1,n,1,i);

sort(r+1,r+1+n,c1); m[0]=-n;

for(int i=1;i<=n;++i) m[i]=max(m[i-1],r[i].l);

for(int i=1;i<=n;++i)

printf("%d\n",min(a[i],i-m[l]+1));

}}

Jzoj2921 NOI2012模擬題 字串識別

題意 給乙個字串,對於每個位置i,求出最短滿足的子串 l,r 使得i l,r 且這個子串只出現一次,輸出這個子串的長度 神 shui 題,ac後看了下別人的code發現全都是字尾陣列 難看 可能是因為我太弱了所以只想到sam的演算法 做法 建立sam,求出parent樹,預處理倍增,讓後就可以o l...

NOI 2012 騎行川藏

題意 在滿足 i vi 0且 n i 1k isi vi t i 2 e 前提下最小化 n i 1s i vi 學習了一下拉格朗日橙子乘子法。對於函式f x1,x 2,xn 和g x1,x 2,xn 在滿足g c c為 常數 的前提下求 f 的最小值。我們直觀地想象,所有極值點一定滿足 f g 令f...

NOI2012 騎行川藏

noi2012 騎行川藏 思路一 二分導數 考慮 價效比 即花費單位能量縮短的時間。如果我們給每一段隨機分配乙個速度,再調整 那麼一定選擇價效比最高的調整,或者把價效比較低的能量取回,再分配 而價效比隨著能量分配,會越來越低 可以發現的是,最後所有的n段的價效比一定都相同!如果存在不同的,那麼一定可...