zoukankan      html  css  js  c++  java
  • UVALive 6869(后缀数组)

    传送门:Repeated Substrings

    题意:给定一个字符串,求至少重复一次的不同子串个数。

    分析:模拟写出子符串后缀并排好序可以发现,每次出现新的重复子串个数都是由现在的height值减去前一个height值。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int maxn = 100010;
    typedef long long LL;
    int sa[maxn];
    int t1[maxn], t2[maxn], c[maxn];
    int ran[maxn], height[maxn];
    int s[maxn];
    char str[maxn];
    
    void build_sa(int s[], int n, int m) {
        int i, j, p, *x = t1, *y = t2;
        for (i = 0; i < m; i++) c[i] = 0;
        for (i = 0; i < n; i++) c[x[i] = s[i]]++;
        for (i = 1; i < m; i++) c[i] += c[i-1];
        for (i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
    
        for (j = 1; j <= n; j <<= 1) {
            p = 0;
            for (i = n-j; i < n; i++) y[p++] = i;
            for (i = 0; i < n; i++)
                if (sa[i] >= j)
                    y[p++] = sa[i] - j;
            for (i = 0; i < m; i++) c[i] = 0;
            for (i = 0; i < n; i++) c[x[y[i]]]++;
            for (i = 1; i < m; i++) c[i] += c[i-1];
            for (i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
    
            swap(x, y);
            p = 1, x[sa[0]] = 0;
            for (i = 1; i < n; i++)
                x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+j] == y[sa[i]+j] ? p-1 : p++;
    
            if (p >= n) break;
            m = p;
        }
    }
    
    void getHeight(int s[],int n) {
        int i, j, k = 0;
        for (i = 0; i <= n; i++)
            ran[sa[i]] = i;
        for (i = 0; i < n; i++) {
            if (k) k--;
            j = sa[ran[i]-1];
            while (s[i+k] == s[j+k]) k++;
            height[ran[i]]=k;
        }
    }
    int main() {
        int T;
        scanf("%d", &T);
        while (T--) {
            scanf("%s", str);
            int n = strlen(str);
            for (int i = 0; i <= n; i++)
                s[i] = str[i];
            build_sa(s, n+1, 128);
            getHeight(s, n);
            LL ans = 0;
            for (int i = 1; i <= n; i++)
            {
                if(height[i]>height[i-1])ans+=height[i]-height[i-1];
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Gridview使用CheckBox全选与单选 Version 2
    Repeater控件第前10笔记录高亮显示
    下拉式菜单(DropDownList)连动的选择
    DataList控件显示图片要的是效果
    电容屏、电阻屏基础知识
    SIM300实现GPRS上网
    qt练习7 定时爆炸小游戏
    用 STL vector 来创建二维数组
    sim300_at命令.doc
    QT练习6 label,button创建,点击按键关闭
  • 原文地址:https://www.cnblogs.com/lienus/p/4459801.html
Copyright © 2011-2022 走看看