0、题意:给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身)。

1、分析:这个题我问了吴大爷做法

首先建立后缀自动机,然后利用离线搞出每一个节点在多少个串中,这个用树状数组统计一下就好,和BZOJ2780一样,然后如果这个节点在不少于x个串中,我们把这个点的value赋值成这个节点父亲边的字符个数,否则为0。随后我们预处理一下从根到每个节点路径上的权值和。于是每个字符串的答案等于所有这个字符串的后缀节点的从根到该节点的权值和。

然后这个题就解决了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 200010
#define LL long long

inline int read(){
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

struct node{
    int tranc[27], fa, len;
} a[202010];
int cnt, tail;
char s[202010];
int p, nq, q, np;
int in[M], out[M], seg[M], num;
int C[M], v[M];
int lastins[M];
int sum[M];

struct gragh{
    int head[M], to[M], Next[M], tot;

    inline void init(){
        memset(head, -1, sizeof(head));
        tot = 0;
    }

    inline void add(int u, int v){
        ++ tot;
        Next[tot] = head[u];
        head[u] = tot;
        to[tot] = v;
    }
} w, G, sam;

struct Query{
    int id, l, r;
    inline bool operator < (const Query& rhs) const{
        return r < rhs.r;
    }
} S[M];

inline void insert(int k, int op){
    p = tail;
    if(a[p].tranc[k] != 0){
        q = a[p].tranc[k];
        if(a[q].len == a[p].len + 1) tail = q;
        else{
            a[nq = ++ cnt] = a[q];
            a[q].fa = nq;
            a[nq].len = a[p].len + 1;
            for(; a[p].tranc[k] == q; p = a[p].fa) a[p].tranc[k] = nq;
            tail = nq;
        }
    }
    else{
        np = ++ cnt;
        a[np].len = a[tail].len + 1;
        for(p = tail; p && !a[p].tranc[k]; p = a[p].fa) a[p].tranc[k] = np;
        if(!p) a[np].fa = 1;
        else{
            q = a[p].tranc[k];
            if(a[q].len == a[p].len + 1) a[np].fa = q;
            else{
                a[nq = ++ cnt] = a[q];
                a[q].fa = a[np].fa = nq;
                a[nq].len = a[p].len + 1;
                for(; a[p].tranc[k] == q; p = a[p].fa) a[p].tranc[k] = nq;
            }
        }
        tail = np;
    }
    w.add(tail, op);
    sam.add(op, tail);
}

inline void dfs(int x){
    in[x] = ++ num; seg[num] = x;
    for(int i = G.head[x]; i != -1; i = G.Next[i]){
        dfs(G.to[i]);
    }
    out[x] = num;
}

inline void change(int x, int d){
    for(; x <= cnt; x += (x & -x)) C[x] += d;
}

inline int ask(int x){
    int ret = 0;
    for(; x > 0; x -= (x & -x)) ret += C[x];
    return ret;
}

inline void dfs2(int x){
    v[x] += v[a[x].fa];
    for(int i = G.head[x]; i != -1; i = G.Next[i]) dfs2(G.to[i]);
}

int main(){
    int n = read(), lim = read();
    cnt = 1;
    G.init(); w.init(); sam.init();
    for(int i = 1; i <= n; i ++){
        scanf("%s", s + 1);
        tail = 1;
        int len = strlen(s + 1);
        for(int j = 1; j <= len; j ++){
            insert(s[j] - 'a' + 1, i);
        }
    }
    for(int i = 1; i <= cnt; i ++){
        if(a[i].fa != 0) G.add(a[i].fa, i);
    }
    dfs(1);
    for(int i = 1; i <= cnt; i ++) S[i] = (Query){i, in[i], out[i]};

    sort(S + 1, S + cnt + 1);
    int k = 1;
    for(int i = 1; i <= cnt; i ++){
        for(int j = w.head[seg[i]]; j != -1; j = w.Next[j]){
            if(lastins[w.to[j]]) change(lastins[w.to[j]], -1);
            change(lastins[w.to[j]] = i, 1);
        }
        while(S[k].r == i) sum[S[k].id] = ask(S[k].r) - ask(S[k].l - 1), k ++;
    }
    for(int i = 1; i <= cnt; i ++){
        if(sum[i] >= lim) v[i] = a[i].len - a[a[i].fa].len;
        else v[i] = 0;
    }
    dfs2(1);
    LL ans = 0;
    for(int i = 1; i <= n; i ++){
        if(i > 1) printf(" ");
        ans = 0;
        for(int j = sam.head[i]; j != -1; j = sam.Next[j]) ans += v[sam.to[j]];
        printf("%lld", ans);
    }
    return 0;
}

BZOJ3277——串的更多相关文章

  1. BZOJ3473&&BZOJ3277串

    BZOJ3473&&BZOJ3277串 题面 自己找去 HINT 对于所有串建立一个广义后缀自动机,对于每一个节点开一个set表示这个节点接受的子串在哪些串里出现过,然后在parent ...

  2. BZOJ3277 串(后缀数组+二分答案+主席树)

    因为不会SAM,考虑SA.将所有串连起来并加分隔符,每次考虑计算以某个位置开始的子串有多少个合法. 对此首先二分答案,找到名次数组上的一个区间,那么只需要统计有多少个所给串在该区间内出现就可以了.这是 ...

  3. bzoj3277 串 (后缀数组+二分答案+ST表)

    常见操作:先把所有串都连到一起,但中间加上一个特殊的符号(不能在原串中/出现过)作为分割 由于全部的子串就等于所有后缀的所有前缀,那我们对于每一个后缀,去求一个最长的前缀,来满足这个前缀在至少K个原串 ...

  4. bzoj3473: 字符串 && bzoj3277串

    3473: 字符串 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 121  Solved: 53[Submit][Status][Discuss] D ...

  5. 【文文殿下】[BZOJ3277] 串

    Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中 至少k个字符串的子串(注意包括本身) Input 第一行两个整数n,k ...

  6. BZOJ3277 串 【广义后缀自动机】

    Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中 至少k个字符串的子串(注意包括本身). Input 第一行两个整数n, ...

  7. bzoj3473字符串&bzoj3277串

    题意:给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串.注意本质相同的子串多次出现算多次,如1 1 aaa这组数据答案为6,贡献1WA.代码里有些部分是为了 ...

  8. BZOJ3277: 串(广义后缀自动机)

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1196  Solved: 478[Submit][Status][Discuss] Descripti ...

  9. BZOJ3277 串(后缀自动机)

    对多串建立SAM的一种方法是加分隔符.于是加完分隔符建出SAM. 考虑统计出每个节点被多少个串包含.让每个串各自在SAM上跑,跑到一个节点就标记(显然一定会完全匹配该节点,因为是对包含其的串建的SAM ...

随机推荐

  1. 生成秘钥文件 sn.exe(Strong Name Tool)

    Visual Studio 内置 Strong Name Tool, 我们直接运行"VS开发人员命令提示"就可以生成秘钥文件. 秘钥文件包含公钥和私钥. 来看这个例子: 在文件夹下 ...

  2. CentOS7安装Nginx并部署

    服务器IP是192.168.36.136 1.直接yum install nginx即可 2.主配置文件是/etc/nginx/下的nginx.conf,另外一个是/etc/nginx/conf.d/ ...

  3. 仿照jquery封装一个自己的js库(二)

    本篇为完结篇.主要讲述如何造出轮子的高级特性. 一. css方法的高级操作 先看本文第一部分所讲的dQuery css方法 //css方法 dQuery.prototype.css=function( ...

  4. int main(int argc, char * argv[]) 里的异常处理

    #import <UIKit/UIKit.h> #import "AppDelegate.h" int main(int argc, char * argv[]) { ...

  5. css中的px、em、rem 详解

    概念介绍: 1.px (pixel,像素):是一个虚拟长度单位,是计算机系统的数字化图像长度单位,如果px要换算成物理长度,需要指定精度DPI(Dots Per Inch,每英寸像素数),在扫描打印时 ...

  6. jar tvf study.war jar命令查看war/jar包的内容

    jar tvf study.war 0 Thu Oct 20 14:01:18 CST 2016 META-INF/ 137 Thu Oct 20 14:01:16 CST 2016 META-INF ...

  7. (转载)ecshop制作成手机网站的方法

    ecshop用手机访问的时候,会自动跳转到  /mobile 目录下,ecshop自带的wap模板是用wml制作的,如果按这种情况,又需要制作一套模板,太麻烦,现在都是智能手机时代,wml模板已经不能 ...

  8. PHP与Javascript的混合测试

    js调用php <?php $num=88; ?> <script> var a = <?php echo $num;?>; alert(a); </scri ...

  9. WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)

    最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...

  10. JSF页面中使用js函数回调后台bean方法并获取返回值的方法

    由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的, ...