題目
\(sam\)+線段樹
我竟然還會寫線段樹真是感人至深
考慮到我們只能計算出現一次的子串,所以我們直接先求乙個子樹和,只對\(|endpos|=1\)的點操作就好了
我們在\(sam\)插入的時候可以先存存好每乙個字首的結尾位置在**,之後我們對於每乙個字首討論其出現次數為\(1\)的字尾
顯然在\(parent\)樹上深度越小的節點的\(len\)就越小,\(|endpos|\)也就越大,於是我們直接從每個字首的結尾節點往上跳,跳到深度最小的\(|endpos|=1\)的節點
這個可以通過樹上倍增做到,不過好像直接暴力看起來更有保障一些
設\(x\)就是我們跳到的點,那麼非常顯然從\(i-len[fa[x]]+1\)到\(i\)這些位置的字尾出現次數超過了\(1\),而從\(1\)到\(i-len[fa[x]]\)這些子串的出現次數為\(1\)
所以對於\([\ 1,i-len[fa[x]]\ ]\)這個區間裡的位置我們都可以標記出乙個其能往後延伸的最近位置,顯然就是\(i\),而我們如果倒著迴圈的話,我們就可以保證\(i\)單減,所以我們甚至可以只用乙個線段樹來通過區間覆蓋進行更新
而對於\([i-len[fa[x]]+1,i]\)這個區間的位置,我們發現其長度都是固定的,為\(len[fa[x]]+1\),但是我們好像不太能保證\(len[fa[x]]+1\)單調
沒有關係啊,我們離線下來排序就好了
**
#include#include#include#include#define maxn 200005
#define re register
#define inf 999999999
#define min(a,b) ((a)
int num,n,lst=1,cnt=1;
char s[maxn>>1];
int to[maxn>>1];
struct e e[maxn];
struct c a[maxn];
int fa[maxn],son[maxn][26],sz[maxn],len[maxn],head[maxn],f[maxn][19],deep[maxn],log_2[maxn];
inline int cmp(c a,c b)
inline void add(int x,int y)
void dfs(int x)
inline void ins(int o,int c)
int x=son[f][c];
if(len[f]+1==len[x])
int y=++cnt;
len[y]=len[f]+1,fa[y]=fa[x],fa[x]=fa[p]=y;
for(re int i=0;i<26;i++) son[y][i]=son[x][i];
while(f&&son[f][c]==x) son[f][c]=y,f=fa[f];
}inline int find(int x)
int l[maxn<<1],r[maxn<<1],tag[maxn<<1],d[maxn>>1],ans[maxn>>1],ans[maxn>>1];
void build(int x,int y,int i)
inline void pushdown(int i)
void change(int x,int y,int val,int i)
pushdown(i);
int mid=l[i]+r[i]>>1;
if(y<=mid) change(x,y,val,i<<1);
else if(x>mid) change(x,y,val,i<<1|1);
else change(x,y,val,i<<1),change(x,y,val,i<<1|1);
}int ask(int pos,int i)
int main()
for(re int i=1;i<=n;i++) d[i]=ask(i,1);
std::sort(a+1,a+n+1,cmp);
build(1,n,1);
for(re int i=1;i<=n;i++) if(a[i].x<=a[i].y) change(a[i].x,a[i].y,a[i].v,1);
for(re int i=1;i<=n;i++) ans[i]=ask(i,1),ans[i]=min(ans[i],d[i]-i+1);
for(re int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}
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...