csu 1305 Substring (后缀数组)

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1305

1305: Substring

Time Limit: 2 Sec  Memory Limit: 10 MB Submit: 12  Solved: 2 [ Submit][ Status][ Web Board]

Description

Given a string s. The length of s is smaller than 1000. You are to caculate the number of different substrings of s.

Input

There are multiple test cases. Each test case contains one line, with a string s.You may assume that s only contains lowercase letters. You may assume that there are only ten test cases with the length of string s is bigger than 400.

Output

For each test case, you are only to output one integer,  the answer.

Sample Input

a
ac
abcd

Sample Output

1
3
10


【题解】:
后缀数组:用(1+2+。。。+len)-(height数组之后)
【code】:
 1 #include <iostream>
 2 #include<string.h>
 3 #include<stdio.h>
 4 
 5 using namespace std;
 6 
 7 #define maxn 10100
 8 #define cls(x) memset(x, 0, sizeof(x))
 9 int wa[maxn],wb[maxn],wv[maxn],wss[maxn];
10 int cmp(int *r,int a,int b,int l)
11 {return r[a]==r[b]&&r[a+l]==r[b+l];}
12 
13 void da(char *r,int *sa,int n,int m)
14 {
15      cls(wa);
16      cls(wb);
17      cls(wv);
18      cls(wss);
19      int i,j,p,*x=wa,*y=wb,*t;
20      for(i=0;i<m;i++) wss[i]=0;
21      for(i=0;i<n;i++) wss[x[i]=r[i]]++;
22      for(i=1;i<m;i++) wss[i]+=wss[i-1];
23      for(i=n-1;i>=0;i--) sa[--wss[x[i]]]=i;
24      for(j=1,p=1;p<n;j*=2,m=p)
25      {
26        for(p=0,i=n-j;i<n;i++) y[p++]=i;
27        for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
28        for(i=0;i<n;i++) wv[i]=x[y[i]];
29        for(i=0;i<m;i++) wss[i]=0;
30        for(i=0;i<n;i++) wss[wv[i]]++;
31        for(i=1;i<m;i++) wss[i]+=wss[i-1];
32        for(i=n-1;i>=0;i--) sa[--wss[wv[i]]]=y[i];
33        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
34        x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
35      }
36      return;
37 }
38 int rank[maxn],height[maxn];
39 void calheight(char *r,int *sa,int n)
40 {
41      cls(rank);
42      cls(height);
43      int i,j,k=0;
44      for(i=1;i<n;i++) rank[sa[i]]=i;
45      for(i=0;i<n;height[rank[i++]]=k)
46      for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k]&&i!=j;k++);
47      return;
48 }
49 
50 char ca[maxn * 2];
51 int sa[maxn];
52 
53 int main()
54 {
55     while (cin >> ca)
56     {
57         int len = strlen(ca);
58         da(ca, sa, len+1, 130);
59         calheight(ca,sa,len+1);
60         int i,sum=0;
61         for(i=1;i<=len;i++)
62         {
63             sum+=height[i];
64         }
65         cout<<len*(len+1)/2-sum<<endl;
66         cls(ca);
67     }
68     return 0;
69 }

 

转载于:https://www.cnblogs.com/crazyapple/p/3293554.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值