2946: [Poi2000]公共串

标签: 后缀自动机
17人阅读 评论(0) 收藏 举报
分类:

一开始理解错了子串的含义,尴尬…
理解了题意.
其实就是个后缀自动机裸题,把第一个串建后缀自动机,然后把所有串放在上面跑即可…
c++代码如下:

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x ; i <= y; ++ i )
#define repd(i,x,y) for(register int i = x ; i >= y; -- i)
using namespace std;
template<typename T>inline bool chkmax(T&x,T y) { return x < y ? x = y,1: 0; }
template<typename T>inline bool chkmin(T&x,T y) { return x > y ? x = y,1: 0; }
template<typename T>inline void read(T&x)
{
    char c;int sign = 1;x = 0;
    do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
    do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c)); 
    x *= sign;
}

const int N = 4e3 + 50;
int p = 1,sz = 1,root = 1;
int f[N],mn[N],ans;
char s[N];
struct SAM { int ch[26],len,pre; }t[N];

inline void insert(int x)
{
    int np = ++ sz;
    mn[np] = t[np].len = t[p].len + 1;
    for(;p && !t[p].ch[x];p = t[p].pre) t[p].ch[x] = np;
    if(!p) t[np].pre = root;
    else
    {
        int q = t[p].ch[x];
        if(t[q].len == t[p].len + 1) t[np].pre = q;
        else
        {
            int nq = ++ sz;
            t[nq] = t[q];
            t[nq].len = t[p].len + 1;
            t[q].pre = t[np].pre = nq;
            for(;p && t[p].ch[x] == q;p = t[p].pre) t[p].ch[x] = nq;
        }
    }
    p = np;
}

int n,l,len,id[N],buc[N];
inline void toposort()
{
    rep(i,1,sz) ++ buc[t[i].len];
    rep(i,1,len) buc[i] += buc[i - 1];
    rep(i,1,sz) id[buc[t[i].len] -- ] = i;
}

int main()
{
    read(n);
    scanf("%s",s + 1);

    len = strlen(s + 1);
    rep(i,1,len) insert(s[i] - 'a');

    toposort();

    rep(ii,2,n)
    {
        memset(f,0,sizeof f);
        scanf("%s",s + 1);
        l = strlen(s + 1);
        int now = 1,le = 0;
        rep(i,1,l)
        {
            int x = s[i] - 'a';
            if(t[now].ch[x]) ++le,now = t[now].ch[x];
            else
            {
                for(;now && !t[now].ch[x];now = t[now].pre) ;
                if(!now) now = root,le = 0;
                else le = t[now].len + 1,now = t[now].ch[x];
            }
            chkmax(f[now],le);
        }

        repd(i,sz,1)
        {
            now = id[i];
            chkmin(mn[now],f[now]);
            chkmax(f[t[now].pre],f[now]);
        }
    }

    rep(i,1,sz) ans = max(ans,mn[i]);

    cout << ans << endl;

    return 0;
}
查看评论

数据结构基础系列(4):串

-
  • 1970年01月01日 08:00

[bzoj2946][后缀数组][Poi2000]公共串

2946: [Poi2000]公共串Time Limit: 3 Sec Memory Limit: 128 MB Submit: 1178 Solved: 527 [Submit][Statu...
  • qq_36993218
  • qq_36993218
  • 2017-07-21 17:26:04
  • 236

bzoj 2946: [Poi2000]公共串

Description          给出几个由小写字母构成的单词,求它们最长的公共子串的长度。 任务: l        读入单词 l        计算最长公共子串的长度...
  • lqybzx
  • lqybzx
  • 2015-06-30 21:51:43
  • 436

2946: [Poi2000]公共串|哈希|后缀数组

据说是后缀自动机裸题 然而,我还没有熟练掌握CE自动机,TLE自动机,RE自动机 并没有达到学习后缀自动机条件………… 后缀数组 : 二分答案,给height数组分组暴力判断 复杂度(nlogn)36...
  • ws_yzy
  • ws_yzy
  • 2016-01-18 20:44:57
  • 435

bzoj2946 [Poi2000]公共串(SAM)

Description给出几个由小写字母构成的单词,求它们最长的公共子串的长度。 任务: 读入单词 计算最长公共子串的长度 输出结果  Input  文件的第一行是整数 n,1,表示单词的数量。接下...
  • wu_tongtong
  • wu_tongtong
  • 2018-01-28 19:34:11
  • 49

[BZOJ2946][Poi2000]公共串

后缀自动机
  • hbhcy98
  • hbhcy98
  • 2016-04-08 07:01:47
  • 307

【bzoj2946】[Poi2000]公共串 后缀自动机

Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度。 任务: l 读入单词 l 计算最长公共子串的长度 l 输出结果I...
  • LOI_DQS
  • LOI_DQS
  • 2016-02-29 21:18:38
  • 389

【POI2000】【BZOJ2946】公共串

2946: [Poi2000]公共串 Time Limit: 3 Sec Memory Limit: 128 MB Submit: 286 Solved: 121 [Submit][Stat...
  • CreationAugust
  • CreationAugust
  • 2015-07-26 17:07:26
  • 1173

bzoj2946 [Poi2000]公共串(SA+二分答案 同poj3450)

求多个串的最长公共子串,一模一样,题解见这里
  • Icefox_zhx
  • Icefox_zhx
  • 2017-08-24 19:52:07
  • 211

BZOJ 2946: [Poi2000]公共串

Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度。 任务: l 读入单词 l 计算最长公共子串的长度 l 输...
  • ypxrain
  • ypxrain
  • 2018-04-11 16:07:22
  • 3
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 2108
    积分: 879
    排名: 6万+
    博客专栏
    文章分类
    文章存档