P4720

后缀自动机SAM

SAM ,对于每个节点维护一个区间 [l,r] 表示这个节点即其儿子能到的最大和最小的原串上的位置

对于每个点,答案为 min(rl+1,len) ,因为要保证不能重复

// 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 中国大陆许可协议进行许可。

posted @   xiaruize  阅读(3)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起