BZOJ4566 找相同字元 字尾自動機

2022-05-27 13:51:09 字數 1356 閱讀 9482

題意

給定兩個字串,求兩個字串相同子串的方案數。

分析那麼將字串s1建sam,然後對於s2的每個字首,都在sam中找出來,並且計數就行。

我一開始的做法是,建乙個u和len,順著s2跑sam,當st[u].next[c]存在的時候,u=st[u].next[c],len++,這時候找到了這個字首的最長公共字尾,然後順著parent邊向上走,然後res+=cnt[u]*(len-st[st[u].link].len)。為什麼是len-st[st[u].link].len。因為對於狀態u,它的有效長度是[st[st[u].link].len+1,st[u].len]。但是這樣寫完以後tle了。然後我就去看了下大佬們的做法。思路也是一樣的只是記錄乙個f陣列。

1 #include 2 #include 3 #include 4 #include 5

6using

namespace

std;

7const

int maxn=200000+100

;8 typedef long

long

ll;9

struct

statest[2*maxn];

13int cnt[2*maxn],c[2*maxn],ap[2*maxn];

14 ll f[2*maxn];

15char

s1[maxn],s2[maxn];

16int

n1,n2;

17int

last,cur,sz;

18void

init()

2425

void build_sam(int

c)48

}49 last=cur;50}

51int cmp(int a,int

b)54

55 ll update(int u,int

len)

61return

res;62}

6364

intmain()

71for(int i=0;i)

72 c[i]=i;

73 sort(c,c+sz,cmp);

74for(int i=0;i)

7980 ll ans=0;81

int u=0,len=0;82

for(int i=0;i)93}

9495

for(int i=0;i)

100for(int i=1;i)

103 printf("

%lld\n

",ans);

104return0;

105 }

view code

BZOJ4566 找相同字元(字尾陣列)

bzoj 字尾陣列的做法,應該不是很難想 首先看到兩個不同的串,當然是接在一起求sa hei ght 那麼,考慮一下暴力 在兩個串各列舉乙個字尾,他們的lc p 就是對答案產生的貢獻 現在優化一下,按照sa 的順序列舉來處理lc p 利用乙個單調棧維護一下,每次記錄一下前面有多少個的貢獻和當前答案一...

bzoj4566 找相同字元

題意 給定兩個字串,從中各取乙個子串使之相同,有多少種取法。允許本質相同。解 建立廣義字尾自動機,對於每個串,分別統計cnt,之後每個點的cnt乘起來。記得開long long 1 include 2 include 3 include 4 5 typedef long long ll 6 cons...

BZOJ4566 找相同字元(字尾自動機)

bzoj 看到多串處理,sa 就連起來 sa m?單串建自動機 然後其他串匹配 對於乙個串建完sa m 後 另乙個串在sa m 上匹配 記錄當前匹配的最大長度 匹配了當前位置的話,就能產生一定的貢獻 但是很顯然,沿著pa rent 往上,所有點都能夠產生貢獻 所以匹配完再沿著pa rent 做一遍類...