zoukankan      html  css  js  c++  java
  • SPOJ 694 && SPOJ 705 (不重复子串个数:后缀数组)

    题意

    给定一个字符串,求它的所有不重复子串的个数

    思路

    一个字符串的子串都必然是它的某个后缀的前缀。对于每一个sa[i]后缀,它的起始位置sa[i],那么它最多能得到该后缀长度个子串(n-sa[i]个),而其中有height[i]个是与前一个后缀相同的,所以它能产生的实际后缀个数便是n-sa[i]-height[i]。遍历一次所有的后缀,将它产生的后缀数加起来便是答案。

    代码

      [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <vector> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) using namespace std; //Suffix Array const int maxn = 1005; int wx[maxn], wy[maxn], wxy[maxn], hs[maxn]; int r[maxn], sa[maxn], ranks[maxn], height[maxn]; int cmp(int r[], int a, int b, int l){ return (r[a] == r[b] && r[a+l] == r[b+l]); } //r is the string, and r[n-1] = 0, this means we should add a '0' at the end of the string. void da(int r[], int sa[], int ranks[], int height[], int n, int m){ //calculate sa[], begin at 1 because sa[0] = "0". int i, j, len, p, k = 0, *x = wx, *y = wy, *t; for (i = 0; i < m; i ++) hs[i] = 0; for (i = 0; i < n; i ++) hs[x[i] = r[i]] ++; for (i = 1; i < m; i ++) hs[i] += hs[i-1]; for (i = n-1; i >= 0; i --) sa[-- hs[x[i]]] = i; for (len = 1, p = 1; p < n; len *= 2, m = p){ for (p = 0, i = n - len; i < n; i ++) y[p ++] = i; for (i = 0; i < n; i ++) if (sa[i] >= len) y[p ++] = sa[i] - len; for (i = 0; i < n; i ++) wxy[i] = x[y[i]]; for (i = 0; i < m; i ++) hs[i] = 0; for (i = 0; i < n; i ++) hs[wxy[i]] ++; for (i = 1; i < m; i ++) hs[i] += hs[i-1]; for (i = n-1; i >= 0; i --) sa[-- hs[wxy[i]]] = y[i]; for (t = x, x = y, y = t, p = 1, i = 1, x[sa[0]] = 0; i < n; i ++) x[sa[i]] = cmp(y, sa[i-1], sa[i], len)?p-1:p ++; } //calculate height[], height[n-1] is null because we add a '0' at the end of the string. for (i = 1; i < n; i ++) ranks[sa[i]] = i; for (i = 0; i < n - 1; height[ranks[i++]] = k) for (k?k--:0, j = sa[ranks[i]-1]; r[i+k] == r[j+k]; k ++); } int main(){ //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); int t; scanf("%d", &t); while(t --){ char tmps[1005] = {0}; scanf("%s", tmps); MEM(r, 0); int n = strlen(tmps); for (int i = 0; i < n; i ++) r[i] = tmps[i]; da(r, sa, ranks, height, n + 1, 100); int res = 0; for (int i = 1; i <= n; i ++){ res += n - sa[i] - height[i]; } printf("%d ", res); } return 0; } [/cpp]
  • 相关阅读:
    通过HttpListener实现简单的Http服务
    WCF心跳判断服务端及客户端是否掉线并实现重连接
    NHibernate初学六之关联多对多关系
    NHibernate初学五之关联一对多关系
    EXTJS 4.2 资料 跨域的问题
    EXTJS 4.2 资料 控件之Grid 那些事
    EXTJS 3.0 资料 控件之 GridPanel属性与方法大全
    EXTJS 3.0 资料 控件之 Toolbar 两行的用法
    EXTJS 3.0 资料 控件之 combo 用法
    EXTJS 4.2 资料 控件之 Store 用法
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114121.html
Copyright © 2011-2022 走看看