求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 一直往上跳,跳到第乙個能匹配的地方跳下去就可...