intlen(int p){ return t[p].len; } intsize(){ return t.size(); } int &cnt(int p){ return t[p].cnt; } voidwork(string s){ int p = 1; //vector<int> pos(1, 0); for (auto x : s) { p = extend(p, x); //pos.push_back(p); } tot = t.size() - 1; //return pos; } voidgetcnt(int len){ vector<int> tong(len + 1); vector<int> id(tot + 1); for (int i = 1; i <= tot; i++) tong[t[i].len]++; // 按照len[x]从小到大基数排序,相当于对SAM图进行拓扑排序 for (int i = 1; i <= len; i++) tong[i] += tong[i - 1]; for (int i = 1; i <= tot; i++) id[tong[t[i].len]--] = i; // 排名为j的节点是状态i for (int i = tot; i >= 1; i--) { auto cur = t[id[i]]; t[cur.fail].cnt += cur.cnt; } // 从后往前for,自底向上更新parent的right大小 } };
给定一个只包含小写字母的字符串 S。字符串的价值为出现次数乘上该子串长度,不考虑只出现一次的子串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
voidsolve(){ string s; cin >> s; SAM sam; sam.work(s); n = s.size(); sam.getcnt(n); ll ans = 0; for (int i = 2; i <= sam.tot; i++) { if (sam.t[i].cnt <= 1) continue; ans = max((ll)sam.t[i].cnt * sam.len(i), ans); } cout << ans << endl; }
voidsolve(){ cin >> n; SAM sam; int p = 1; for (int i = 1; i <= n; i++) { cin >> a[i]; p = sam.extend(p, a[i]); } for (int i = 1; i <= n; i++) { p = sam.extend(p, a[i]); } p = 1; vector<int>res; for (int i = 1; i <= n; i++) { for (int j = 0; j <= 30; j++) { if (sam.next(p, j)) { res.push_back(j); p = sam.next(p, j); break; } } } for(auto x:res)cout<<x<<" "; }
voidsolve(){ string s, t;cin >> s >> t; SAM sam; sam.work(s); int ans = 0;int res = 0; int p = 1; for (auto x : t) { int tmp = sam.next(p, x); if (tmp) { res++;p = tmp; } else { int q = sam.fail(p); while (q != 1 && sam.next(q, x) == 0) q = sam.fail(q); // 可能根本没有这个匹配根本没有模式串的字母 p = sam.next(q, x); if (p)res = sam.len(q) + 1; else res = 0,p = 1; //及时还原正确的起点 } ans = max(ans, res); } cout << ans << endl; }
int &lc(int p){ return t[p].lc; } int &tmplc(int p){ return t[p].tmplc; } voidgetlc(int len){ vector<int> tong(len + 1); vector<int> id(tot + 1); for (int i = 1; i <= tot; i++) tong[t[i].len]++; // 按照len[x]从小到大基数排序,相当于对SAM图进行拓扑排序 for (int i = 1; i <= n; i++) tong[i] += tong[i - 1]; for (int i = 1; i <= tot; i++) id[tong[t[i].len]--] = i; // 排名为j的节点是状态i for (int i = tot; i >= 1; i--) { auto cur = t[id[i]]; deb(cur.fail, id[i]); t[cur.fail].lc = max(t[cur.fail].lc, cur.lc); } // 从后往前for,自底向上更新parent的right大小 } SAM sam; int ans = 0; voidduo(string t){ int tot = sam.tot; int tmp = 0; int p = 1; for (auto x : t) { if (sam.next(p, x)) { tmp++; p = sam.next(p, x); } else { while (p > 1 && sam.next(p, x) == 0) p = sam.fail(p); if (sam.next(p, x)) { tmp = sam.len(p) + 1; p = sam.next(p, x); } else tmp = 0; } sam.lc(p) = max(sam.lc(p), tmp); } sam.getlc(n); for (int i = 1; i <= tot; i++) { sam.tmplc(i) = min(sam.tmplc(i), sam.lc(i)); sam.lc(i) = 0; } } voidsolve(){ cin >> m; string s; vector<string> v(m); int mn = inf; int id = 0; for (int i = 0; i < m; i++) { cin >> v[i]; if (mn > (int)v[i].size()) { mn = v[i].size(); id = i; } } s = v[id]; n = s.size(); sam.work(s); // deb(s); int tot = sam.tot; for (int i = 0; i < m; i++) { if (id == i) continue; duo(v[i]); } for (int i = 2; i <= tot; i++) ans = max(ans, min(sam.len(i), sam.tmplc(i))); cout << ans << endl; }
8.本质不同子串:造S 的SAM,∑stateL[state]−L[f(state)] 即为答案
1 2 3 4 5 6
voidsolve(){ string s;cin>>s; SAM sam;sam.work(s);ll ans=0; for(int i=2;i<=sam.tot;i++)ans+=sam.len(i)-sam.len(sam.fail(i)); cout<<ans<<endl; }
voidsolve(){ string s; while (cin >> s) { SAM sam; sam.work(s); cin >> m; int ans = 0; int tot = sam.tot; vector<int> sg(tot + 1); vector<bool> vis(tot + 1); auto dfs = [&](auto self, int u) { if (vis[u]) return; vis[u] = true; set<ll> st; for (int i = 0; i < 26; i++) { if (sam.next(u, i)) { int tmp = sam.next(u, i); self(self, tmp); st.insert(sg[tmp]); } } while (st.count(sg[u])) sg[u]++; }; dfs(dfs, 1); auto cal = [&](string &t) { int p = 1; for (auto x : t) { p = sam.next(p, x); } return sg[p]; }; for (int i = 1; i <= m; i++) { string tt; cin >> tt; ans ^= cal(tt); } if (ans == 0) cout << "Bob" << endl; else cout << "Alice" << endl; } }
char tmp = 'z' + 1; voidsolve(){ int n; cin >> n; vector<string> q(n + 1); for (int i = 1; i <= n; i++) cin >> q[i]; SAM sam; string s; for (int i = 1; i <= n; i++) s += q[i] + tmp; sam.work(s); int len = s.size(); sam.getcnt(len); auto query = [&](string t) { int p = 1; for (auto x : t) { if (sam.next(p, x) == 0) return0; else p = sam.next(p, x); } return sam.cnt(p); }; for (int i = 1; i <= n; i++) { cout << query(q[i]) << endl; } }