[SPOJ705]不同的子串

题目描述】

给定一个字符串,计算其不同的子串个数。

【输入格式】

一行一个仅包含大写字母的字符串,长度<=50000

【输出格式】

一行一个正整数,即不同的子串个数。

【样例输入】

ABABA

【样例输出】

9

 

题解:

显然后缀可以是一个子串,然后后缀中可能包含多个子串。

我们考虑不重复统计,容易发现 一个后缀的贡献为L-high[i]+1

因为high[i]之前的显然可以在后面的串中被统计到,所以可以避免重复

 

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 using namespace std;
 8 const int N=50005;
 9 char s[N];int n,k,rk[N],sa[N],tmp[N],high[N];
10 bool comp(int i,int j){
11     if(rk[i]!=rk[j])return rk[i]<rk[j];
12     int ri=i+k<=n?rk[i+k]:-1;
13     int rj=j+k<=n?rk[j+k]:-1;
14     return ri<rj;
15 }
16 void Getsa(){
17     for(int i=1;i<=n;i++)sa[i]=i,rk[i]=s[i];
18     for(k=1;k<=n;k<<=1){
19         sort(sa+1,sa+n+1,comp);
20         for(int i=1;i<=n;i++)tmp[sa[i]]=tmp[sa[i-1]]+comp(sa[i-1],sa[i]);
21         for(int i=1;i<=n;i++)rk[i]=tmp[i];
22     }
23 }
24 void Gethight(){
25     int j,h=0;
26     for(int i=1;i<=n;i++){
27         j=sa[rk[i]-1];
28         if(h)h--;
29         for(;j+h<=n && i+h<=n;h++)if(s[i+h]!=s[j+h])break;
30         high[rk[i]-1]=h;
31     }
32 }
33 void Getanswer(){
34     long long ans=0;
35     for(int i=1;i<=n;i++){
36         if(high[i]==n-sa[i]+1)continue;
37         ans+=n-sa[i]+1-high[i];
38     }
39     printf("%lld\n",ans);
40 }
41 int main()
42 {
43     freopen("subst1.in","r",stdin);
44     freopen("subst1.out","w",stdout);
45     scanf("%s",s+1);
46     n=strlen(s+1);
47     Getsa();Gethight();Getanswer();
48     return 0;
49 }

 

转载于:https://www.cnblogs.com/Yuzao/p/7172277.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
洛谷的SPOJ需要注册一个SPOJ账号并进行绑定才能进行交题。您可以按照以下步骤进行注册: 1. 打开洛谷网站(https://www.luogu.com.cn/)并登录您的洛谷账号。 2. 在网站顶部导航栏中找到“题库”选项,将鼠标悬停在上面,然后选择“SPOJ”。 3. 在SPOJ页面上,您会看到一个提示,要求您注册SPOJ账号并进行绑定。点击提示中的链接,将会跳转到SPOJ注册页面。 4. 在SPOJ注册页面上,按照要求填写您的用户名、密码和邮箱等信息,并完成注册。 5. 注册完成后,返回洛谷网站,再次进入SPOJ页面。您会看到一个输入框,要求您输入刚刚注册的SPOJ用户名。输入用户名后,点击“绑定”按钮即可完成绑定。 现在您已经成功注册并绑定了SPOJ账号,可以开始在洛谷的SPOJ题库上刷题了。祝您顺利完成编程练习!\[1\]\[2\] #### 引用[.reference_title] - *1* *3* [(洛谷入门系列,适合洛谷新用户)洛谷功能全解](https://blog.csdn.net/rrc12345/article/details/122500057)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [luogu p7492 序列](https://blog.csdn.net/zhu_yin233/article/details/122051384)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值