SAM入门

学了两天,会了点皮毛,这里只放代码。

P3804

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;++i)
#define lv(i,a,n) for(register int i = a;i >= n;--i)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 1e6 + 5;
struct node
{
    int ch[27];
    int len,fa;
    node()
    {
        clean(ch);
        len = 0;
    }
}dian[N << 1];
int las = 1,tot = 1;
int len;
char s[N];
int buc[N << 1],siz[N << 1],pos[N << 1];
inline void add(int c)
{
    int p = las;int np = las = ++tot;
    dian[np].len = dian[p].len + 1;
    for(;p && !dian[p].ch[c];p = dian[p].fa)
    dian[p].ch[c] = np;
    if(!p) dian[np].fa = 1;
    else
    {
        int q = dian[p].ch[c];
        if(dian[q].len == dian[p].len + 1) dian[np].fa = q;
        else
        {
            int nq = ++tot;
            dian[nq] = dian[q];
            dian[nq].len = dian[p].len + 1;
            dian[q].fa = dian[np].fa = nq;
            for(;p && dian[p].ch[c] == q;p = dian[p].fa) dian[p].ch[c] = nq;
        }
    }
    siz[np] = 1;
}
/*void add(int c)
{
    int p=las;int np=las=++tot;
    dian[np].len=dian[p].len+1;
    for(;p&&!dian[p].ch[c];p=dian[p].fa)dian[p].ch[c]=np;
    if(!p)dian[np].fa=1;//以上为case 1
    else
    {
        int q=dian[p].ch[c];
        if(dian[q].len==dian[p].len+1)dian[np].fa=q;//以上为case 2
        else
        {
            int nq=++tot;dian[nq]=dian[q];
            dian[nq].len=dian[p].len+1;
            dian[q].fa=dian[np].fa=nq; 
            for(;p&&dian[p].ch[c]==q;p=dian[p].fa)dian[p].ch[c]=nq;//以上为case 3
        }
    }
    siz[las = np] = 1;
}*/
inline int dfs()
{
    int ret = 0;
    duke(i,1,tot)
        ++buc[dian[i].len];
    duke(i,1,tot)
        buc[i] += buc[i - 1];
    duke(i,1,tot)
    pos[buc[dian[i].len]--] = i;
    for(int i = tot;i;i--)
    {
        int now = pos[i];
        siz[dian[now].fa] += siz[now];
        if(siz[now] > 1)
        ret = max(ret,siz[now] * dian[now].len);
    }
    return ret;
}
int main()
{
    scanf("%s",s);
    len = strlen(s);
    duke(i,0,len - 1)
    {
        add(s[i] - 'a');
    }
    printf("%d
",dfs());
    return 0;
}

SP1811

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;++i)
#define lv(i,a,n) for(register int i = a;i >= n;--i)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 250005;
struct node
{
    int fa,len;
    int ch[27];
    node()
    {
        len = 0;
        clean(ch);
    }
}dian[N << 1];
int tot = 1,las = 1,len1,len2;
char s1[N],s2[N];
inline void add(int c)
{
    int p = las;int np = las = ++tot;
    dian[np].len = dian[p].len + 1;
    for(;p && !dian[p].ch[c];p = dian[p].fa)
    dian[p].ch[c] = np;
    if(!p) dian[np].fa = 1;
    else
    {
        int q = dian[p].ch[c];
        if(dian[q].len == dian[p].len + 1) dian[np].fa = q;
        else
        {
            int nq = ++tot;
            dian[nq] = dian[q];
            dian[nq].len = dian[p].len + 1;
            dian[q].fa = dian[np].fa = nq;
            for(;p && dian[p].ch[c] == q;p = dian[p].fa) dian[p].ch[c] = nq;
        }
    }
}
inline int Max(int x,int y)
{
    return x < y ? y : x;
}
inline int lcs(char *s)
{
    int n = strlen(s),ret = 0;
    for(int i = 0,p = 1,l = 0;i < n;++i)
    {
        int c = s[i] - 'a';
        if(dian[p].ch[c] != 0) l++,p = dian[p].ch[c];
        else
        {
            for(;p && !dian[p].ch[c];p = dian[p].fa) ;
            if(!p) l = 0,p = 1;
            else
            {
                l = dian[p].len + 1;
                p = dian[p].ch[c];
            }
        }
        ret = Max(ret,l);
    }
    return ret;
}
int main()
{
    scanf("%s",s1);
    scanf("%s",s2);
    len1 = strlen(s1);
    len2 = strlen(s2);
    for(register int i = 0;i < len1;++i)
    {
        add(s1[i] - 'a');
    }
    printf("%d
",lcs(s2));
    return 0;
}

SP1812

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;++i)
#define lv(i,a,n) for(register int i = a;i >= n;--i)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 1e5 + 5;
struct node
{
    int fa,len;
    int ch[27];
    node()
    {
        clean(ch);
        len = 0;
    }
} dian[N << 1];
char s1[N],s2[N];
int las = 1,tot = 1;
inline void add(int c)
{
    int p = las;
    int np = las = ++tot;
    dian[np].len = dian[p].len + 1;
    for(; p && !dian[p].ch[c]; p = dian[p].fa)
        dian[p].ch[c] = np;
    if(!p) dian[np].fa = 1;
    else
    {
        int q = dian[p].ch[c];
        if(dian[q].len == dian[p].len + 1) dian[np].fa = q;
        else
        {
            int nq = ++tot;
            dian[nq] = dian[q];
            dian[nq].len = dian[p].len + 1;
            dian[q].fa = dian[np].fa = nq;
            for(; p && dian[p].ch[c] == q; p = dian[p].fa) dian[p].ch[c] = nq;
        }
    }
}
int pos[N << 1],buc[N << 1],Max[N << 1],Min[N << 1];
inline void dfs(char *s)
{
    int n = strlen(s);
    for(int i = 0,p = 1,l = 0; i < n; ++i)
    {
        int c = s[i] - 'a';
        for(; p && !dian[p].ch[c];) p = dian[p].fa,l = dian[p].len;
        if(!p) l = 0,p = 1;
        else
        {
            l ++;
            p = dian[p].ch[c];
            Max[p] = max(Max[p],l);
        }
    }
    for(int i = tot; i >= 1; --i)
    {
        int now = pos[i],f = dian[now].fa;
        Max[f] = max(Max[f],min(Max[now],dian[f].len));
        Min[now] = min(Min[now],Max[now]);
        Max[now] = 0;
    }
}
void sort()
{
    duke(i,1,tot)
    ++buc[dian[i].len];
    duke(i,1,tot)
    buc[i] += buc[i - 1];
    duke(i,1,tot)
    pos[buc[dian[i].len] --] = i;
}
int main()
{
    scanf("%s",s1);
    int len1 = strlen(s1);
    for(register int i = 0; i < len1; ++i)
    {
        add(s1[i] - 'a');
    }
    sort();
    memset(Min,0x3f,sizeof(Min));
    clean(Max);
    while(scanf("%s",s2) != EOF)
    {
        dfs(s2);
    }
    int ans = 0;
    duke(i,1,tot)
    ans = max(ans,Min[i]);
    printf("%d
",ans);
    return 0;
}

 P2852 [USACO06DEC]牛奶模式Milk Patterns

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;++i)
#define lv(i,a,n) for(register int i = a;i >= n;--i)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 2e4 + 5;
struct node
{
    int len,fa;
    int ch[27];
    node()
    {
    clean(ch);
    len = 0;
    }
}dian[N << 1];
int las = 1,tot = 1;
int n,k;
int x,pos[N << 1],siz[N << 1];
void add(int c)
{
    int p = las;int np = las = ++tot;
    dian[np].len = dian[p].len + 1;
    siz[np] = 1;
    for(;p && !dian[p].ch[c];p = dian[p].fa)
    dian[p].ch[c] = np;
    if(!p) dian[np].fa = 1;
    else
    {
    int q = dian[p].ch[c];
    if(dian[q].len == dian[p].len + 1)
        dian[np].fa = q;
    else
    {
        int nq = ++tot;
        dian[nq] = dian[q];
        dian[nq].len = dian[p].len + 1;
        dian[q].fa = dian[np].fa = nq;
        for(;p && dian[p].ch[c] == q;p = dian[p].fa) dian[p].ch[c] = nq;
    }
    }
}
int dfs()
{
    int ret = 0;
    for(int i = 1;i <= tot;i++)
    pos[i] = i;
    sort(pos + 1,pos + tot + 1,[=](int &a,int &b){return dian[a].len > dian[b].len;});
    for(int i = 1;i <= tot;++i)
    {
    siz[dian[pos[i]].fa] += siz[pos[i]];
    if(siz[pos[i]] >= k)
    {
        ret = max(ret,dian[pos[i]].len);
    }
    }
    return ret;
}
int main()
{
    read(n);read(k);
    for(int i = 1;i <= n;++i)
    read(x),add(x);
    printf("%d
",dfs());
    return 0;
}

 P3975 [TJOI2015]弦论

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;++i)
#define lv(i,a,n) for(register int i = a;i >= n;--i)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 5e5 + 5;
struct node
{
    int len,fa;
    int ch[27];
}dian[N << 1];
char s[N];
int las = 1,tot = 1;
int n,k,flg;
int x,pos[N << 1],siz[N << 1],buc[N << 1],sum[N << 1];
void add(int c)
{
    int p = las;int np = las = ++tot;
    dian[np].len = dian[p].len + 1;
    siz[np] = 1;
    for(;p && !dian[p].ch[c];p = dian[p].fa)
    dian[p].ch[c] = np;
    if(!p) dian[np].fa = 1;
    else
    {
    int q = dian[p].ch[c];
    if(dian[q].len == dian[p].len + 1)
        dian[np].fa = q;
    else
    {
        int nq = ++tot;
        dian[nq] = dian[q];
        dian[nq].len = dian[p].len + 1;
        dian[q].fa = dian[np].fa = nq;
        for(;p && dian[p].ch[c] == q;p = dian[p].fa) dian[p].ch[c] = nq;
    }
    }
}
inline void dfs()
{
    for(int i = 1; i <= tot; ++i)
    ++buc[dian[i].len];
    for(int i = 1; i <= tot; ++i)
    buc[i] += buc[i - 1];
    for(int i = 1; i <= tot; ++i)
    pos[buc[dian[i].len]--] = i;
    for(int i = tot; i; --i)
    siz[dian[pos[i]].fa] += siz[pos[i]];
    for(int i = 1; i <= tot; ++i)
    {
    if(!flg)
        sum[i] = siz[i] = 1;
    else
        sum[i] = siz[i];
    }
    siz[1] = 0;
    for(int i = tot; i; --i)
    for(int j = 0; j < 26; ++j)
        if(dian[pos[i]].ch[j])
        sum[pos[i]] += sum[dian[pos[i]].ch[j]];
}
inline void print(int k)
{
    if(sum[1] < k)
    {
    printf("-1
");
    return;
    }
    int now = 1;
    k -= siz[now];
    while(k)
    {
    int c = 0;
    while(k > sum[dian[now].ch[c]])
    {
        k -= sum[dian[now].ch[c++]];
    }
    now = dian[now].ch[c];
    putchar('a' + c);
    k -= siz[now];
    }
}
int main()
{
    scanf("%s",s);
    n = strlen(s);
    duke(i,0,n << 1)
    dian[i].len = 0,clean(dian[i].ch);
    duke(i,0,n - 1)
    add(s[i] - 'a');
    read(flg);read(k);
    dfs();
    print(k);
    puts("");
    return 0;
}

 P4070 [SDOI2016]生成魔咒

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;++i)
#define lv(i,a,n) for(register int i = a;i >= n;--i)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 2e5 + 5;
struct node
{
    int fa;
    ll len;
    map <int,int> ch;
}dian[N << 1];
char s[N];
int las = 1,tot = 1;
int n,k;
ll ans = 0;
int x;
void add(int c)
{
    int p = las;int np = las = ++tot;
    dian[np].len = dian[p].len + 1;
    for(;p && !dian[p].ch[c];p = dian[p].fa)
    dian[p].ch[c] = np;
    if(!p) dian[np].fa = 1,ans += dian[np].len;
    else
    {
    int q = dian[p].ch[c];
    if(dian[q].len == dian[p].len + 1)
        dian[np].fa = q,ans += dian[np].len - dian[q].len;
    else
    {
        int nq = ++tot;
        dian[nq] = dian[q];
        dian[nq].len = dian[p].len + 1;
        ans -= dian[q].len - dian[dian[q].fa].len;
        dian[q].fa = dian[np].fa = nq;
        ans += dian[nq].len - dian[dian[nq].fa].len;
        ans += dian[q].len - dian[nq].len;
        ans += dian[np].len - dian[nq].len;
        for(;p && dian[p].ch[c] == q;p = dian[p].fa) dian[p].ch[c] = nq;
    }
    }
}
int main()
{
    read(n);
    while(n--)
    {
    int c;
    read(c);
    add(c);
    printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/DukeLv/p/10474131.html