先上模板
int len[maxn << 1],fa[maxn << 1],son[maxn << 1][maxc]; LL num[maxn << 1]; int size,last; void Init(){ size = last = 1; } void insert(char c){ int s = c - ‘a‘; int p = last,np = ++size;last = np; num[np] = 1; //主链结点出现次数 + 1 len[np] = len[p] + 1; for(;p && !son[p][s]; p = fa[p]) son[p][s] = np; if(!p) fa[np] = 1; else{ int q = son[p][s]; if(len[p] + 1 == len[q]) fa[np] = q; else{ int nq = ++size; len[nq] = len[p] + 1; memcpy(son[nq],son[q],sizeof(son[q])); fa[nq] = fa[q]; fa[q] = fa[np] = nq; for(;son[p][s] == q && p;p = fa[p]) son[p][s] = nq; } } } void insert(char *s){ Init(); for(int i = 0; s[i] ; i ++) insert(s[i]); }
9.10 update
P3804 【模板】后缀自动机
dfs parent树可以统计每个子串出现的次数
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<‘0‘ || c>‘9‘){if (c == ‘-‘) f = -1;c = getchar();} while (c >= ‘0‘&&c <= ‘9‘){x = x * 10 + c - ‘0‘;c = getchar();}return x*f;} const double PI = acos(-1.0); const double eps = 1e-9; const int maxn = 1e6 + 10; const int maxc = 26; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int len[maxn << 1],fa[maxn << 1],son[maxn << 1][maxc]; LL num[maxn << 1]; int size,last; void Init(){ size = last = 1; } void insert(char c){ int s = c - ‘a‘; int p = last,np = ++size;last = np; num[np] = 1; len[np] = len[p] + 1; for(;p && !son[p][s]; p = fa[p]) son[p][s] = np; if(!p) fa[np] = 1; else{ int q = son[p][s]; if(len[p] + 1 == len[q]) fa[np] = q; else{ int nq = ++size; len[nq] = len[p] + 1; memcpy(son[nq],son[q],sizeof(son[q])); fa[nq] = fa[q]; fa[q] = fa[np] = nq; for(;son[p][s] == q && p;p = fa[p]) son[p][s] = nq; } } } void insert(char *s){ Init(); for(int i = 0; s[i] ; i ++) insert(s[i]); } char str[maxn]; struct Edge{ int to,next; }edge[maxn << 1]; int head[maxn << 1],tot; void init(){ for(int i = 0; i <= size; i ++) head[i] = -1; tot = 0; } void add(int u,int v){ edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void dfs(int t){ for(int i = head[t]; ~i ; i = edge[i].next){ int v = edge[i].to; dfs(v); num[t] += num[v]; } } int main(){ scanf("%s",str); insert(str); init(); for(int i = 2; i <= size; i ++) add(fa[i],i); dfs(1); LL ans = 0; for(int i = 2; i <= size; i ++) if(num[i] != 1)ans = max(ans,len[i] * num[i]); Prl(ans); return 0; }
P1368 工艺
最小表示法,将原串倍增一遍插入,SAM上直接寻找长度为N的字典序最小的路径
因为是倍增了一遍,脑补证明往任意点出发必定能找到长度至少为N的路径,所以甚至不需要dfs,直接跑即可
const int maxn = 6e5 + 10; int N,M,K; int len[maxn << 1],fa[maxn << 1]; map<int,int>son[maxn << 1]; int size,last; void Init(){ size = last = 1; } inline void insert(int c){ int p = last,np = ++size; last = np; len[np] = len[p] + 1; for(;p && !son[p].count(c); p = fa[p]) son[p][c] = np; if(!p) fa[np] = 1; else{ int q = son[p][c]; if(len[p] + 1 == len[q]) fa[np] = q; else{ int nq = ++size; len[nq] = len[p] + 1; son[nq] = son[q]; fa[nq] = fa[q]; fa[q] = fa[np] = nq; for(;son[p][c] == q && p; p = fa[p]) son[p][c] = nq; } } } int a[maxn]; int main(){ Sca(N); Init(); for(int i = 1; i <= N ; i ++) insert(a[i] = read()); for(int i = 1; i <= N ; i ++) insert(a[i]); int t = 1; for(int i = 1; i <= N ; i ++){ printf("%d ",son[t].begin()->first); t = son[t].begin()->second; } return 0; }
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <bitset> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x) #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x) #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<‘0‘ || c>‘9‘){if (c == ‘-‘) f = -1;c = getchar();} while (c >= ‘0‘&&c <= ‘9‘){x = x * 10 + c - ‘0‘;c = getchar();}return x*f;} const double PI = acos(-1.0); const double eps = 1e-9; const int maxn = 5e5 + 10; const int maxc = 26; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int len[maxn << 1],fa[maxn << 1],son[maxn << 1][maxc]; int size,last; int num[maxn << 1]; void Init(){ size = last = 1; } void insert(char c){ int s = c - ‘a‘; int p = last,np = ++size;last = np;num[np] = 1; len[np] = len[p] + 1; for(;p && !son[p][s]; p = fa[p]) son[p][s] = np; if(!p) fa[np] = 1; else{ int q = son[p][s]; if(len[p] + 1 == len[q]) fa[np] = q; else{ int nq = ++size; len[nq] = len[p] + 1; memcpy(son[nq],son[q],sizeof(son[q])); fa[nq] = fa[q]; fa[q] = fa[np] = nq; for(;son[p][s] == q && p; p = fa[p]) son[p][s] = nq; } } } void insert(char *s){ Init(); for(int i = 0;s[i]; i ++) insert(s[i]); } char str[maxn]; int tmp[maxn << 1],A[maxn << 1]; int sum[maxn << 1]; void dfs(int t,int k){ if(k <= num[t]) return; k -= num[t]; for(int i = 0 ; i < 26; i ++){ if(!son[t][i]) continue; int v = son[t][i]; if(sum[v] >= k){ printf("%c",i + ‘a‘); dfs(v,k); return; } k -= sum[v]; } } int main(){ scanf("%s",str); insert(str); for(int i = 1; i <= size; i ++) tmp[len[i]]++; for(int i = 1; i <= size; i ++) tmp[i] += tmp[i - 1]; for(int i = 1; i <= size; i ++) A[tmp[len[i]]--] = i; for(int i = size; i >= 1; i --) num[fa[A[i]]] += num[A[i]]; int op = read(),k = read(); for(int i = 1; i <= size; i ++) sum[i] = op?num[i]:num[i] = 1; sum[1] = num[1] = 0; for(int i = size; i >= 1; i --){ for(int j = 0 ; j < 26; j ++){ if(son[A[i]][j]) sum[A[i]] += sum[son[A[i]][j]]; } } if(sum[1] < k) puts("-1"); else dfs(1,k); return 0; }
留坑
原文地址:https://www.cnblogs.com/Hugh-Locke/p/11502775.html
时间: 2024-11-10 18:45:29