bzoj1396 識別子串

2022-05-31 06:06:11 字數 2029 閱讀 6047

題解:

首先我們知道對於size==1的點是只出現一次的

存疑:為什麼新增點不會size==1

那麼問題就變成區間取等差數列,區間取最小值

分別線段樹維護就可以了

**:

#include #define il inline

#define ll long long

#define rint register int

#define rep(i,h,t) for (rint i=h;i<=t;i++)

#define dep(i,t,h) for (rint i=t;i>=h;i--)

using

namespace

std;

const

int inf=1e9;

const

int n=3e5;

char

s[n];

int size[n],len[n],ch[n][26

];int lst=1,node=1

,t[n],a[n],fa[n],pos[n],pl;

void extend(int

c)

int p=++node; lst=p;

len[p]=len[f]+1; //

size[p][pl]=1;

while (f&&!ch[f][c]) ch[f][c]=p,f=fa[f];

if (!f) ;

int x=ch[f][c],y=++node;

if (len[f]+1==len[x]) ;

len[y]=len[f]+1; fa[y]=fa[x]; fa[x]=fa[p]=y;

memcpy(ch[y],ch[x],

sizeof

(ch[x]));

while (f&&ch[f][c]==x) ch[f][c]=y,f=fa[f];

}il

int min(int x,int

y)il

int max(int x,int

y)il

void minn(int &x,int

y)il

void maxn(int &x,int

y)const

int n1=n*4

;struct

sgt

#define mid ((h+t)/2)il

void down(int x,int h,int

t)

void change1(int x,int h,int t,int h1,int t1,int

k)

down(x,h,t);

if (h1<=mid) change1(x*2

,h,mid,h1,t1,k);

if (mid2+1,mid+1,t,h1,t1,k-(mid-h+1

)); }

void change2(int x,int h,int t,int h1,int t1,int

k)

down(x,h,t);

if (h1<=mid) change2(x*2

,h,mid,h1,t1,k);

if (mid2+1,mid+1

,t,h1,t1,k);

} int query(int x,int h,int t,int

pos)

down(x,h,t);

if (pos<=mid) return(query(x*2

,h,mid,pos));

else

return(query(x*2+1,mid+1

,t,pos));

}}s;

intmain()

rep(i,

1,node)

if (size[i]==1)

rep(i,

1,n)

cout

<1,1,n,i)

}

BZOJ 1396 識別子串

solution 我得了 能用字尾陣列就一定不用字尾自動機綜合症 感覺用height rank sa 處理字串真的好優雅 雖然其他題上字尾陣列常數比較大 不過這個字尾陣列水了一發似乎就rank1 了 開心 題解就是求出字尾陣列以後維護乙個單調佇列來更新答案啦。include include incl...

Bzoj1396 識別子串

i 1,n i 1,n 求包含 i i 並且在原串 s role presentation style position relative s s中只出現一次的子串的最短長度 因為每個點pa rent p ar en t樹上的父親肯定是當前節點所代表的串的字尾 那麼只出現一次的串就是pa rent ...

BZOJ1396 識別子串

列舉左端點 i 那麼可行的右端點 j 的最小值單調不下降,可以通過雙指標求出,檢驗可以通過在字尾陣列裡檢查相鄰height值做到 o 1 那麼左端點為 i 右端點在 j,n 它對前面一段的貢獻為定值,對後面一段的貢獻為等差數列,線段樹維護即可。時間複雜度 o n log n include incl...