• HDU5558(后缀自动机~在本串中找前一最长子相同串)


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

    题意:

     当前的位置是 i , 就找到 s1 = ( 以i为起点到 len 的连续串 ) , s2=( 在 [0,i)内选一个起点到 len 的连续串) , 要求s1==s2 ; 如果有输出( 最大的长度 , 在[0,i)内选取的起点 ) , 如果找不到就输出(-1 ,ASCLL(str[i]) )

    分析:

    利用SAM的联机特性 , 一边插入一边找答案 , 还要求最小的下标就多维护一个first_endpos

    就是找到一个最大的某后缀 , 比如:从起始状态不断的用当前字符str[i] , 往后面转移 , 不断的p=trans[p][str[i]] , 就是说找到str[i]的最大后缀

    #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 = 1e6+550;
    #define mid ((l + r) >> 1)
    #define lc rt<<1
    #define rc rt<<1|1
    using namespace std;
    // __int128 read() {    __int128 x = 0, f = 1;  char c = getchar(); while (c < '0' || c > '9') {        if (c == '-') f = -1;       c = getchar();  }   while (c >= '0' && c <= '9') {      x = x * 10 + c - '0';       c = getchar();  }   return x * f;}
    // void print(__int128 x) { if (x < 0) {        putchar('-');       x = -x; }   if (x > 9)  print(x / 10);  putchar(x % 10 + '0');}
    
    int len;
    struct SAM{
    
        int trans[maxn<<1][26], slink[maxn<<1], maxlen[maxn<<1];
        // 用来求endpos
        int endpos[maxn<<1];
        // 计算所有子串的和(0-9表示)
        int last, now, root;
    
        inline void newnode (int v) {
            maxlen[++now] = v;
            mem(trans[now],0);
        }
    
        inline void extend(int c,int i) {
            newnode(maxlen[last] + 1);
            int p = last, np = now;
            endpos[np]=i;
            // 更新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;
                    endpos[nq]=endpos[q];
                    memcpy(trans[nq], trans[q], sizeof(trans[q]));
                    slink[nq] = slink[q];
                    slink[q] = slink[np] = nq;
                    while (p && trans[p][c] == q) {
                        trans[p][c] = nq;
                        p = slink[p];
                    }
                }else slink[np] = q;
            }
            last = np;
            // 初始状态为可接受状态
    
        }
    
    
        inline void init()
        {
            root = last = now = 1;
            slink[root]=0;
            mem(trans[root],0);
           //endpos[root]=0;
        }
    
    
    
    
    }sam;
    
    int main()
    {
        //printf("%d ",maxn);
        int t;scanf("%d",&t);
        for(int w=1 ; w<=t ; w++){
    
        string T;cin>>T;
        sam.init();
       len=T.size();printf("Case #%d:
    ",w);
        for(int i=0 ; i<len ; )
        {
            int p=sam.root , k=0;
            while(i < len && sam.trans[p][T[i]-'a'])
            {
               p=sam.trans[p][T[i]-'a'];
               sam.extend(T[i]-'a',i);
               k++ , i++;
            }
            //printf("%d
    ",p);
            if(k) printf("%d %d
    ",k,sam.endpos[p]-k+1);
            else
            {
                sam.extend(T[i]-'a',i);
                printf("-1 %d
    ",(int)T[i]);
                i++;
            }
        }
    
        }
       //- sam.all();
    }
    View Code
  • 相关阅读:
    【leetcode】416. Partition Equal Subset Sum
    【leetcode】893. Groups of Special-Equivalent Strings
    【leetcode】892. Surface Area of 3D Shapes
    【leetcode】883. Projection Area of 3D Shapes
    【leetcode】140. Word Break II
    【leetcode】126. Word Ladder II
    【leetcode】44. Wildcard Matching
    【leetcode】336. Palindrome Pairs
    【leetcode】354. Russian Doll Envelopes
    2017.12.22 英语面试手记
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10693142.html
Copyright © 2020-2023  润新知