bzoj 2865 字串識別 字尾陣列 線段樹

2021-08-16 12:50:37 字數 1667 閱讀 2613

在這個問題中,給定乙個字串s,與乙個整數k,定義s的子串t=s(i, j)是關於第k位的識別子串,滿足以下兩個條件:

1、i≤k≤j。

2、子串t只在s中出現過一次。

例如,s=」banana」,k=5,則關於第k位的識別子串有」nana」,」anan」,」anana」,」nan」,」banan」和」banana」。

現在,給定s,xx希望知道對於s的每一位,最短的識別子串長度是多少,請你來幫助他。

n<=500000

先把字尾數組建出來,然後對於每乙個字尾p,我們可以知道以它為開頭且在s中只出現一次的串的長度區間,設為[l,r]。

對於在[p,p+l-1]中的位置,字尾p對它們答案的貢獻是l。對於[p+l,p+r-1]中的位置pos,字尾p對它們答案的貢獻是pos-p+1。

那麼我們只要用線段樹分別維護一下兩種貢獻的最小值即可。

#include

#include

#include

#include

#include

using namespace std;

const int n=500005;

const int inf=1000000000;

int n,s[n],b[n],c[n],d[n],rank[n*2],sa[n],height[n],pos,mn;

char str[n];

struct treet[n*4];

void get_sa(int n,int

m) while (j<=n)

for (int i=1;i<=n;i++) rank[i]=c[i];

if (t==n) break;

j<<=1;

}for (int i=1;i<=n;i++) sa[rank[i]]=i;

}void get_height(int n)

height[1]=0;

}void build(int d,int l,int r)

void ins1(int d,int l,int r,int

x,int

y,int z)

int mid=(l+r)/2;

if (y

<=mid) ins1(d*2,l,mid,x,y,z);

else

if (x>mid) ins1(d*2+1,mid+1,r,x,y,z);

else ins1(d*2,l,mid,x,mid,z),ins1(d*2+1,mid+1,r,mid+1,y,z);

}void ins2(int d,int l,int r,int

x,int

y,int z)

int mid=(l+r)/2;

if (y

<=mid) ins2(d*2,l,mid,x,y,z);

else

if (x>mid) ins2(d*2+1,mid+1,r,x,y,z);

else ins2(d*2,l,mid,x,mid,z),ins2(d*2+1,mid+1,r,mid+1,y,z);

}void query(int d,int l,int r,int

x)int main()

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

return

0;}

bzoj2865 字串識別 字尾自動機 線段樹

description xx在進行字串研究的時候,遇到了乙個十分棘手的問題。在這個問題中,給定乙個字串s,與乙個整數k,定義s的子串t s i,j 是關於第k位的識別子串,滿足以下兩個條件 1 i k j。2 子串t只在s中出現過一次。例如,s banana k 5,則關於第k位的識別子串有 nan...

BZOJ3473 字串 廣義字尾自動機

今天主攻了下sam 好多東西以前都沒理解到 對於這道題 我們建乙個自動機存所有串 每個穿last從1開始 對於自動機上每個點額外記乙個cnt 表示能匹配到這個點的不同串個數 建完對每個串在自動機上匹配 把到的每個點x和par x par par x 的cnt 然後就從父親往兒子傳遞一下 這樣每個點i...

BZOJ 3473 字串 廣義字尾自動機

time limit 20 sec memory limit 256 mb submit 354 solved 160 submit status discuss 給定n個字串,詢問每個字串有多少子串 不包括空串 是所有n個字串中至少k個字串的子串?第一行兩個整數n,k。接下來n行每行乙個字串。一行...