Warning: session_start(): open(/tmp/sess_fa501258a618c04f7a84c1bbe76b9153, O_RDWR) failed: No space left on device (28) in /data/wiki/inc/init.php on line 239

Warning: session_start(): Failed to read session data: files (path: ) in /data/wiki/inc/init.php on line 239

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/auth.php on line 430
Writing /data/wiki/data/cache/d/de2edb2fcb553ea79b79c722a4e13dbc.captchaip failed

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/actions.php on line 38

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/lib/tpl/dokuwiki/main.php on line 12
2020-2021:teams:legal_string:jxm2001:字符串_3 [CVBB ACM Team]

用户工具

站点工具


2020-2021:teams:legal_string:jxm2001:字符串_3

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
2020-2021:teams:legal_string:jxm2001:字符串_3 [2020/08/31 13:02]
jxm2001
2020-2021:teams:legal_string:jxm2001:字符串_3 [2020/09/02 10:52] (当前版本)
jxm2001
行 1: 行 1:
 ====== 字符串 3 ====== ====== 字符串 3 ======
  
-===== 后缀数组 =====+===== 后缀数组(SA) =====
  
 ==== 算法简介 ==== ==== 算法简介 ====
行 41: 行 41:
 <code cpp> <code cpp>
 namespace SA{ namespace SA{
- int sa[MAXN],​rk[MAXN],​height[MAXN],​x[MAXN],y[MAXN],​c[MAXN];​+ int sa[MAXN],​rk[MAXN],​height[MAXN],​X[MAXN],Y[MAXN],​c[MAXN];​
  int d[MAXN][MAXM],​lg2[MAXN];​  int d[MAXN][MAXM],​lg2[MAXN];​
  void get_sa(char *s,int n,int m){//​s下标从1开始  void get_sa(char *s,int n,int m){//​s下标从1开始
 + int *x=X,*y=Y;
  _rep(i,​0,​m)c[i]=0;​  _rep(i,​0,​m)c[i]=0;​
  _rep(i,​1,​n)c[x[i]=s[i]]++;​  _rep(i,​1,​n)c[x[i]=s[i]]++;​
行 588: 行 589:
 于是 $\text{dp}_i=\sum_{1\le j\lt i}\text{LCP}(T_i,​T_j)=\text{dp}_j+(i-j)\text{height}_i$。 于是 $\text{dp}_i=\sum_{1\le j\lt i}\text{LCP}(T_i,​T_j)=\text{dp}_j+(i-j)\text{height}_i$。
  
-另外该题也可以用笛卡尔树维护。+另外该题也可以用笛卡尔树或并查集等维护。 
 + 
 +<hidden 查看代码>​ 
 +<code cpp> 
 +const int MAXN=5e5+5,​MAXM=20;​ 
 +namespace SA{ 
 + int sa[MAXN],​rk[MAXN],​height[MAXN],​x[MAXN],​y[MAXN],​c[MAXN];​ 
 + void get_sa(char *s,int n,int m){ 
 + _rep(i,​0,​m)c[i]=0;​ 
 + _rep(i,​1,​n)c[x[i]=s[i]]++;​ 
 + _rep(i,​1,​m)c[i]+=c[i-1];​ 
 + for(int i=n;​i;​i--)sa[c[x[i]]--]=i;​ 
 + for(int k=1;​k<​n;​k<<​=1){ 
 + int pos=0; 
 + _rep(i,​n-k+1,​n)y[++pos]=i;​ 
 + _rep(i,​1,​n)if(sa[i]>​k)y[++pos]=sa[i]-k;​ 
 + _rep(i,​0,​m)c[i]=0;​ 
 + _rep(i,​1,​n)c[x[i]]++;​ 
 + _rep(i,​1,​m)c[i]+=c[i-1];​ 
 + for(int i=n;​i;​i--)sa[c[x[y[i]]]--]=y[i],​y[i]=0;​ 
 + swap(x,​y);​ 
 + pos=0,​y[n+1]=0;​ 
 + _rep(i,​1,​n)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&​y[sa[i]+k]==y[sa[i-1]+k])?​pos:​++pos;​ 
 + if(pos==n)break;​ 
 + m=pos; 
 +
 + _rep(i,​1,​n)rk[sa[i]]=i;​ 
 +
 + void get_height(char *s,int n){ 
 + for(int i=1,​k=0;​i<​=n;​i++){ 
 + if(k)k--;​ 
 + while(s[i+k]==s[sa[rk[i]-1]+k])k++;​ 
 + height[rk[i]]=k;​ 
 +
 +
 +
 +char buf[MAXN];​ 
 +pair<​int,​int>​ Stack[MAXN];​ 
 +LL dp[MAXN]; 
 +int main() 
 +
 + scanf("​%s",​buf+1);​ 
 + int n=strlen(buf+1);​ 
 + SA::​get_sa(buf,​n,'​z'​);​ 
 + SA::​get_height(buf,​n);​ 
 + LL ans=1LL*(n-1)*n*(n+1)/​2;​ 
 + int top=0; 
 + Stack[0]=make_pair(0,​0);​ 
 + _rep(i,​1,​n){ 
 + while(top&&​Stack[top].second>​SA::​height[i])top--;​ 
 + dp[i]=dp[Stack[top].first]+1LL*(i-Stack[top].first)*SA::​height[i],​ans-=dp[i]*2;​ 
 + Stack[++top]=make_pair(i,​SA::​height[i]);​ 
 +
 + enter(ans);​ 
 + return 0; 
 +
 +</​code>​ 
 +</​hidden>​
2020-2021/teams/legal_string/jxm2001/字符串_3.1598850175.txt.gz · 最后更改: 2020/08/31 13:02 由 jxm2001