• HDU4622 (查询一段字符串的不同子串个数,后缀自动机)


    http://acm.hdu.edu.cn/showproblem.php?pid=4622

    题意:给出一个字符串和q次询问,每次询问[l,r]区间内不同子串的个数

    分析:

    N<=2000.

    我是用后缀自动机预处理出所有区间的不同子串个数。

    建立n次后缀自动机。

    为什么要建立N次呢? 因为鸭 , 后缀自动机之所以有继承性是因为定义的起点是相同的 , 而起点不同是没有继承性的  , 所以要枚举n次不同的节点建立后缀自动机。

    用一个变量t , 不断的累加建立到当前点有多少个不同的字符串 , 就是前缀和的思想

    #include <bits/stdc++.h>
    #define LL long long
    #define P pair<int, int>
    #define lowbit(x) (x & -x)
    #define mem(a, b) memset(a, b, sizeof(a))
    #define rep(i, a, n) for (int i = a; i <= n; ++i)
    const int maxn = 2005;
    #define mid ((l + r) >> 1)
    #define lc rt<<1
    #define rc rt<<1|1
    using namespace std;
    
    struct SAM{
    
        int trans[maxn<<1][26], slink[maxn<<1], maxlen[maxn<<1];
        int last, now, root, len;
        inline void newnode (int v) {
            maxlen[++now] = v;
        }
    
        inline int extend(int c) {
            newnode(maxlen[last] + 1);
            int p = last, np = now;
            // 更新trans
            while (p && !trans[p][c]) {
                trans[p][c] = np;
                p = slink[p];
            }
            if (!p) slink[np] = root;
            else {
                int q = trans[p][c];
                if (maxlen[p] + 1 != maxlen[q]) {
                    // 将q点拆出nq,使得maxlen[p] + 1 == maxlen[q]
                    newnode(maxlen[p] + 1);
                    int nq = now;
                    memcpy(trans[nq], trans[q], sizeof(trans[q]));
                    slink[nq] = slink[q];
                    slink[q] = slink[np] = nq;
                    while (p!=-1 && trans[p][c] == q) {
                        trans[p][c] = nq;
                        p = slink[p];
                    }
                }else slink[np] = q;
            }
            last = np;
            // 初始状态为可接受状态
            return maxlen[np]-maxlen[slink[np]];
        }
       inline void init()
       {
           memset(trans,0,sizeof(trans));
           memset(slink,0,sizeof(slink));
           memset(maxlen,0,sizeof(maxlen));
           root = last=now=1;
       }
    
    }sam;
    int ans[maxn][maxn];
    int main()
    {
    
        int t;scanf("%d",&t);
        while(t--)
        {
            string str;cin>>str;
    
            for(int i=0 ; i<str.size() ; i++)
            {
                sam.init();
                int T=0;
                for(int j=i ; j<str.size() ; j++)
                {
                    T+=sam.extend(str[j]-'a');
                    ans[i+1][j+1]=T;
                }
            }
            int q;scanf("%d",&q);
            while(q--)
            {
                int u,v;scanf("%d%d",&u,&v);
                printf("%d
    ",ans[u][v]);
            }
        }
    
    
    
       //- sam.all();
    }
    View Code
  • 相关阅读:
    64位Windows2008下插入Oracle中文乱码问题解决
    .net自定义WebService WSDL
    IE8下调用Active控件
    IIS7.5下发布应用程序备忘
    在aws ec2上使用root用户登录
    win2008 服务器文件夹权限配置
    thinkphp3.1 多表联合查询代码
    并发 并行 同步 异步 多线程的区别
    学习ES6生成器(Generator)
    node.js+socket.io配置详解
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10686674.html
Copyright © 2020-2023  润新知