vijosP1567子串计数

描述
现在有一个字符串,请求出这个字符串不相同的子串个数。
YXY现在不会做,请你来帮忙……

n<=20W

题解:

后缀数组裸题,其实我在练习模板写对了没

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<iostream>
 7 #include<vector>
 8 #include<map>
 9 #include<set>
10 #include<queue>
11 #include<string>
12 #define inf 1000000000
13 #define maxn 200000+5
14 #define maxm 500+100
15 #define eps 1e-10
16 #define ll long long
17 #define pa pair<int,int>
18 #define for0(i,n) for(int i=0;i<=(n);i++)
19 #define for1(i,n) for(int i=1;i<=(n);i++)
20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
22 #define mod 1000000007
23 using namespace std;
24 inline int read()
25 {
26     int x=0,f=1;char ch=getchar();
27     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
28     while(ch>=‘0‘&&ch<=‘9‘){x=10*x+ch-‘0‘;ch=getchar();}
29     return x*f;
30 }
31 int n,c[maxn],sa[maxn],rk[maxn],h[maxn],t[maxn],t2[maxn];
32 char s[maxn];
33 void build(int m)
34 {
35     int *x=t,*y=t2;
36     for0(i,m)c[i]=0;
37     for0(i,n)c[x[i]=s[i]]++;
38     for1(i,m)c[i]+=c[i-1];
39     for3(i,n,0)sa[--c[x[i]]]=i;
40     for(int k=1;k<=n+1;k<<=1)
41     {
42         int p=0;
43         for2(i,n-k+1,n)y[p++]=i;
44         for0(i,n)if(sa[i]>=k)y[p++]=sa[i]-k;
45         for0(i,m)c[i]=0;
46         for0(i,n)c[x[y[i]]]++;
47         for1(i,m)c[i]+=c[i-1];
48         for3(i,n,0)sa[--c[x[y[i]]]]=y[i];
49         swap(x,y);
50         p=1;x[sa[0]]=0;
51         for1(i,n)x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
52         if(p>=n+1)break;
53         m=p-1;
54     }
55 }
56 void calch()
57 {
58     for1(i,n)rk[sa[i]]=i;
59     for(int i=0,k=0,j;i<n;h[rk[i++]]=k)
60      for(k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
61 }
62 int main()
63 {
64     freopen("input.txt","r",stdin);
65     freopen("output.txt","w",stdout);
66     n=read();int len=0;
67     while(len<n)
68     {
69         scanf("%s",s+len);
70         len=strlen(s);
71     }
72     s[n]=‘ ‘;
73     build(128);
74     calch();
75     ll ans=0;
76     for1(i,n)ans+=(ll)(n-sa[i]-h[i]);
77     cout<<ans<<endl;
78     return 0;
79 }

这次的模板比上次好多了。。。

时间: 2024-10-11 17:57:24

vijosP1567子串计数的相关文章

【暴力Treap 或 离线归并】子串计数(genies)

子串计数(genies) Description 给出一段含有n个元素的序列a,要求求出子串和小于等于t的子串个数 Input Data 输入共两行第一行包含两个整数,n,t分别表示序列a元素的个数和限制t第二行包含n个数表示元素a_i Output Data 共一行,含一个数表示子串和小于等于t的子串个数.  Input / Output Sample input #1: 5 4 5 -1 3 4 -1 output #1:7 Solution: 一道妙题,首先分析性质.如果从L+1到R可以构

后缀自动机(SAM)学习指南

*在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符串所有后缀的自动机. 它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到. 在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 可以用 SAM 轻松水过,由此 SAM 流行了起来. 一般来说,能用后缀自动机解决的问题都可以用后缀数组解决.但是后缀自动机也拥有自己的优点. 1812.

后缀自己主动机(SAM)学习指南

*在学习后缀自己主动机之前须要熟练掌握WA自己主动机.RE自己主动机与TLE自己主动机* 什么是后缀自己主动机 后缀自己主动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造.可以接受一个字符串全部后缀的自己主动机. 它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到. 在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 能够用 SAM 轻松水过.由此 SAM 流行了起来. 一般来说.能用后缀自己主动机解决的问题都能够用后缀数组解决.可是后缀自己

后缀自动机(SAM)

*在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符串所有后缀的自动机. 它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到. 在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 可以用 SAM 轻松水过,由此 SAM 流行了起来. 一般来说,能用后缀自动机解决的问题都可以用后缀数组解决.但是后缀自动机也拥有自己的优点. 1812.

笔试算法题(30):从已排序数组中确定数字出现的次数 &amp; 最大公共子串和最大公共序列(LCS)

出题:在已经排序的数组中,找出给定数字出现的次数: 分析: 解法1:由于数组已经排序,所以可以考虑使用二分查找确定给定数字A的第一个出现的位置m和最后一个出现的位置n,最后m-n+1就是A出现的次数:使用二分查找可疑快速确定给定数字,但是如果确定其左右范围则比较麻烦,对编码细节要求较高: 解法2:HashTable解决 解题: 1 int occurrence(int *array, int length, int t) { 2 /** 3 * 寻找t所在的区间 4 * 此阶段之后left和ri

字符串替换函数

// 参数说明: // in, 源字符串 // out, 存放最后结果的字符串 // outlen,out最大的大小 // src,要替换的字符串 // dst,替换成什么字符串 /******************************************************************** *  Function:   str_replace() *  Description: 在一个字符串中查找一个子串,并且把所有符合的子串用 另一个替换字符串替换. *  Call

后缀自动机/后缀树

只是笔记罢了,不要看 关于DAWG: 见紫书P390 把后缀自动机上所有节点都设为接受态就形成DAWG,可以接受一个字符串的所有子串. 一个子串的end-set是它在原串w中出现位置(从1开始编号)的右端点集合. 在DAWG中,end-set相同的子串属于同一个状态. 原因没原因,这应该算定义吧? 任意两个节点的end-set要么不相交,要么是包含关系. 原因:在DAWG上走一步,当前end-set的变化是将原end-set中各个元素+1(要去掉超出字符串长度的元素),然后拆分成1个或多个新en

计数二进制子串

export default (str) => { // 建立数据结构,堆栈,保存数据 let r = [] // 给定任意子输入都返回第一个符合条件的子串 let match = (str) => { let j = str.match(/^(0+|1+)/)[0] let o = (j[0] ^ 1).toString().repeat(j.length) let reg = new RegExp(`^(${j}${o})`) if (reg.test(str)) { return Reg

HDU 3518 Boring counting(后缀数组啊 求字符串中不重叠的重复出现至少两次的子串的个数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3518 Problem Description 035 now faced a tough problem,his english teacher gives him a string,which consists with n lower case letter,he must figure out how many substrings appear at least twice,moreover