P4720
后缀自动机SAM
建 SAM
,对于每个节点维护一个区间 表示这个节点即其儿子能到的最大和最小的原串上的位置
对于每个点,答案为 ,因为要保证不能重复
// Author: xiaruize #ifndef ONLINE_JUDGE bool start_of_memory_use; #endif #include <bits/stdc++.h> using namespace std; #ifndef ONLINE_JUDGE clock_t start_clock = clock(); #endif #define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int, int> #define pis pair<int, string> #define sec second #define fir first #define sz(a) int((a).size()) #define Yes cout << "Yes" << endl #define YES cout << "YES" << endl #define No cout << "No" << endl #define NO cout << "NO" << endl #define mms(arr, n) memset(arr, n, sizeof(arr)) #define rep(i, a, n) for (int i = (a); i <= (n); ++i) #define per(i, n, a) for (int i = (n); i >= (a); --i) int max(int a, int b) { if (a > b) return a; return b; } int min(int a, int b) { if (a < b) return a; return b; } const int INF = 0x3f3f3f3f3f3f3f3f; const int MOD = 1000000007; const int N = 2e5 + 10; int n, a, b, c, d; bool s[N]; struct SAM { struct node { int len, lnk, nxt[2]; int mi, mx; } s[N]; int cnt = 1, la = 1; void ins(int x, int id) { int cur = ++cnt, p = la; s[cur].len = s[la].len + 1; while (p && !s[p].nxt[x]) { s[p].nxt[x] = cur; p = s[p].lnk; } int q = s[p].nxt[x]; if (!p) s[cur].lnk = 1; else if (s[p].len + 1 == s[q].len) s[cur].lnk = q; else { int r = ++cnt; s[r] = s[q]; s[r].len = s[p].len + 1; s[r].mx = 0; s[r].mi = n; while (p && s[p].nxt[x] == q) { s[p].nxt[x] = r; p = s[p].lnk; } s[cur].lnk = s[q].lnk = r; } s[cur].mi = s[cur].mx = id; la = cur; } } sam; vector<int> g[N]; void dfs(int x) { for (auto v : g[x]) { dfs(v); sam.s[x].mi = min(sam.s[x].mi, sam.s[v].mi); sam.s[x].mx = max(sam.s[x].mx, sam.s[v].mx); } } void solve() { cin >> a >> b >> c >> d >> n; for (int i = 0; i < a; ++i) { b = (b * c + d) % n; s[b + 1] = true; } rep(i, 1, n) sam.ins(s[i], i); rep(i, 2, sam.cnt) g[sam.s[i].lnk].push_back(i); dfs(1); int res = 0; rep(i, 2, sam.cnt) res += max(min(sam.s[i].mx - sam.s[i].mi, sam.s[i].len) - sam.s[sam.s[i].lnk].len, 0ll); cout << res << endl; } #ifndef ONLINE_JUDGE bool end_of_memory_use; #endif signed main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int testcase = 1; // cin >> testcase; while (testcase--) solve(); #ifndef ONLINE_JUDGE cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl; cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl; #endif return 0; }
本文作者:xiaruize's Blog
本文链接:https://www.cnblogs.com/xiaruize/p/18105729
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步