发现对SAM还是相当的不熟悉。。。专门开一个SAM练习好了。。。估计以后还要来个字符串恶补。。。
挖坑:3277 3473 3413 2806 2780 2555 3897
【bzoj3998】
求第k小子字符串,分算上重复和不算上重复。
十分地裸,如果不算重的话除了root以外所有节点的val都是1然后求sum,如果算的话就只是后缀节点的val是1然后再求sum。
很sb啦
然而把add写错了,查了半个小时QAQ
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define maxn 2000007
typedef long long ll;
typedef int arr[maxn];
typedef int sam[maxn][26];
int n , tot , ed , T;
arr len , fa , cnt , tp ;
sam go;
int val[maxn] , sum[maxn] , K;
void add(int c , int l) {
int p = ed , np = ed = ++ tot;
len[np] = len[p] + 1, val[np] = 1;
for(;p && !go[p][c];p = fa[p]) go[p][c] = np;
if (!p)
{ fa[np] = 1 ; return ; }
int q = go[p][c] ;
if (len[q] == len[p] + 1)
{ fa[np] = q ; return ; }
int r = ++ tot ; len[r] = len[p] + 1;
memcpy(go[r] , go[q] , sizeof go[q]);
for(fa[r] = fa[q] , fa[q] = fa[np] = r;go[p][c] == q;p = fa[p]) go[p][c] = r;
}
void tpsort() {
rep(i , 1 , tot) cnt[len[i]] ++;
rep(i , 1 , n ) cnt[i] += cnt[i - 1];
per(i , tot , 1) tp[cnt[len[i]] --] = i;
per(i , tot , 1) {
int u = tp[i];
if (T) val[fa[u]] += val[u]; else val[u] = 1;
}
val[1] = 0;
per(i , tot , 1) {
int u = tp[i];
sum[u] = val[u];
rep(c , 0 , 25) sum[u] += sum[go[u][c]];
}
}
void dfs(int u) {
if (K <= val[u]) return ;
K -= val[u];
rep(i , 0 , 25) {
int v = go[u][i];
if (!v) continue;
if (sum[v] >= K) {
putchar(i + 'a');
dfs(v);
return;
}
K -= sum[v];
}
}
void input() {
ed = tot = 1;
for(char c = getchar();c <= 'z' && c >= 'a';c = getchar()) add(c - 'a' , n ++);
scanf("%d%d" , &T , &K);
}
void solve() {
tpsort();
if (sum[1] < K) puts("-1");
else dfs(1);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
freopen("data.out" , "w" , stdout);
#endif
input();
solve();
return 0;
}
【bzoj3172】
做了半年的题啊哈哈哈哈哈哈
以此达成bzoj 100A
强行用SAM代替AC自动机啊哈哈哈哈哈
脑残写法
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define maxn 2500007
typedef int arr[maxn];
typedef int sam[maxn][27];
arr len , val , fa , cnt , tp;
sam go;
char str[maxn];
int n , l , tot , ed;
void add(int c) {
int p = ed , np = ed = ++ tot ;
len[np] = len[p] + 1;
val[np] = 1;
for(;p && !go[p][c];p = fa[p]) go[p][c] = np;
if (!p)
{ fa[np] = 1 ; return ; }
int q = go[p][c];
if (len[q] == len[p] + 1)
{ fa[np] = q ; return ; }
int r = ++ tot ; len[r] = len[p] + 1;
memcpy(go[r] , go[q] , sizeof go[q]);
for(fa[r] = fa[q] , fa[q] = fa[np] = r;go[p][c] == q;p = fa[p]) go[p][c] = r;
}
void tpsort() {
rep(i , 1 , tot) cnt[len[i]] ++;
rep(i , 1 , l ) cnt[i] += cnt[i - 1];
per(i , tot , 1) tp[cnt[len[i]] -- ] = i;
per(i , tot , 1) val[fa[tp[i]]] += val[tp[i]];
}
void input() {
scanf("%d" , &n) , getchar();
ed = tot = 1;
rep(i , 1 , n) {
for(char c = getchar();c <= 'z' && c >= 'a';c = getchar()) add(c - 'a') , str[++ l] = c;
str[++ l] = 'a' + 26;
add(26);
}
}
void solve() {
tpsort();
int j = 0;
rep(i , 1 , n) {
int u = 1;
while (str[++ j] != 'a' + 26) u = go[u][str[j] - 'a'];
printf("%d\n" , val[u]);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
freopen("data.out" , "w" , stdout);
#endif
input();
solve();
return 0;
}