字尾自動機求多個串的公共子串數目

2021-10-11 19:06:06 字數 1391 閱讀 5639

求n個串的本質不同公共子串的數目。

我的做法是對第乙個串構造sam,同時得到每個狀態節點在原串的位置。

然後對剩下的n-1的個串在第乙個串的sam上跑,可以得到每個狀態節點

的最長匹配長度,這時候就得到了節點數目個區間,將區間合併,對這些

區間形成的串再建乙個廣義字尾自動機,求出本質不同串的數目。

時間複雜度上面,主要在於這個區間的操作次數。對區間進行了合併,時間複雜度線性。

#include using namespace std;

typedef long long ll;

typedef unsigned long long ull;

const int mod = 1e9 + 7;

const int n = 1e5 + 10;

const int inf = 0x3f3f3f3f;

const ll linf = 0x3f3f3f3f3f3f3f3f;

string s[n];

char t[n];

int f[n << 1], bucket[n << 1], id[n << 1], ans, ls;

int d[n << 1];

struct suffix_automata

void clear()

void extend(int c, int y)

int x = ++idx;

len[x] = len[last] + 1;

pos[x] = y;

for (p = last; p && !nxt[p][c]; p = lnk[p])

nxt[p][c] = x;

if (!p)

lnk[x] = 1;

else

}last = x;

} void get_sub2()

void solve(string& b)

for (int i = idx; i >= 2; i--)

}}sam1, sam2;

int mxl[n << 1];

int main()

vector>v;

int mi = len;

for (int i = len - 1; i >= 0; i--)

); }

sam2.init();

int tot = 0;

for (auto &i : v)

ll res = 0;

for (int i = 2; i <= sam2.idx; i++)

res += sam2.len[i] - sam2.len[sam2.lnk[i]];

cout << res << endl;

return 0;

}

3277 3473 串 字尾自動機

description 字串是oi界常考的問題。現在給定你n個字串,詢問每個字串有多少子串 不包括空串 是所有n個字串中至少k個字串的子串 注意包括本身 首先建出廣義字尾自動機,建的時候順便預處理每個節點代表的串在多少個字串中出現,預處理的方法和2780是一樣的。然後用f i f i 表示 i i ...

字串 字尾自動機

struct sam void extend int c if p 0 int q nxt p c if len p 1 len q int v siz mc nxt v nxt q len v len p 1 lnk v lnk q cnt v 0 while p 0 nxt p c q lnk ...

WOJ3750 子串查詢 字尾自動機

給定乙個字串 a和1個字串 b 求 b 和 a 中的最長公共子串。len a b 2e5 只需要對乙個串建乙個sam samsa m 然後把另乙個串在上面跑就是了 如果發現當前已匹配好的地方的下乙個字元不一樣,就沿著當前節點的lin klink link 一直往上跳,跳到第乙個能匹配的地方跳下去就可...