zoukankan      html  css  js  c++  java
  • 混子的 后缀数组 刷题记录

    洛谷P3809 【模板】后缀排序

    • 先来一道最水的模板题o(*≧▽≦)ツ┏━┓
    • sa[nmax]  sa[i]     排名为i的数的下标是多少
    • x[nmax]    x[i]       值,value,这个每次循环都要根据排名更新一遍
    • y[nmax]    y[i]       两次作为中间数组使用,第一次根据sa[i]更新第二关键字排名为i的数第一关键字的位置,第二次更新x[i](由于比较的时候用到原来x[i]的值,所以先用y[i]更新,最后把y[i]赋值给x[i])
    • qsort()函数   知道了每个数第二关键字的排名(y[i])和第一个关键字的值(x[i])求数的排名,用基数排序,结果在sa[i]里面
    • 每次循环完的状态: x[i] , sa[i] 已经求出
    • 最外层循环的 l :对应当前的sa[i]的l,在本次循环之后sa[i]指代的长度变为 2l
    • 所以 l<n (或者<=n/2) 
    • 好容易写错啊这个后缀数组。。。代码里是一些容易错的点
    • 代码:
       1 #include <bits/stdc++.h>
       2 #define nmax 1000010
       3 
       4 using namespace std;
       5 int c[nmax],rk[nmax],sa[nmax],x[nmax],y[nmax];
       6 //y[i]第二关键字排名为i的数第一关键字的位置
       7 
       8 char s[nmax];
       9 int n,k,m=200;
      10 
      11 void qsort(){
      12     for (int i=1; i<=m; i++) c[i]=0;
      13     for (int i=1; i<=n; i++) c[ x[i] ]++;
      14     for (int i=1; i<=m; i++) c[i]+=c[i-1];
      15     for (int i=n; i>=1; i--) sa[ c[ x[y[i]] ]-- ]=y[i];
      16 }
      17 
      18 int main(){
      19     scanf("%s",s+1);
      20     n=strlen(s+1);
      21     for (int i=1; i<=n; i++) x[i]=s[i];
      22     for (int i=1; i<=n; i++) y[i]=i;
      23     qsort();
      24     for (int l=1; l<n; l<<=1) { 
      25         int t=0;
      26         for (int i=n-l+1; i<=n; i++) y[++t]=i; 
      27         //有些数字是没有第一关键字的,有些数字的第二关键字不在sa[i]能覆盖的范围内
      28         for (int i=1; i<=n; i++) if(sa[i]>l) y[++t]=sa[i]-l;  //如果有第一关键字
      29         qsort();
      30         m=1;
      31         y[ sa[1] ]=m;
      32         for (int i=2; i<=n; i++) {
      33             //这里容易错,sa[i]指代的长度有2l,但是x指代的长度只有l,所以第二关键字也要比较
      34             if( x[sa[i]]==x[sa[i-1]] ) if( x[ sa[i]+l ]==x[sa[i-1]+l] ) { y[ sa[i] ]=m; continue; }
      35             y[ sa[i] ]=++m;
      36         }
      37         for (int i=1; i<=n; i++) x[i]=y[i];
      38     }
      39     for (int i=1; i<=n; i++) printf("%d ",sa[i]);
      40     return 0;
      41 }
      (<ゝω・)☆

    POJ2774 Long Long Message

    • 题意:求两个串的最长公共子串
    • 在两个串中间加一个特殊字符平成一个串,然后在height里面找最大值就行了,注意判断一下是不是一个串里重复出现的字串
    • 代码:
       1 #include <cstdio>
       2 #include <iostream>
       3 #include <algorithm>
       4 #include <cstring>
       5 #define nmax 200010
       6 
       7 using namespace std;
       8 int x[nmax],y[nmax],sa[nmax],c[nmax],he[nmax],rk[nmax],a[nmax];
       9 char in[nmax];
      10 int n,m,ans,la,lb;
      11 
      12 inline void qsort(){
      13     for (int i=0; i<=m; i++) c[i]=0;
      14     for (int i=1; i<=n; i++) c[ x[i] ]++;
      15     for (int i=1; i<=m; i++) c[i]+=c[i-1];
      16     for (int i=n; i>=1; i--) sa[ c[ x[ y[i] ] ]-- ]=y[i];
      17 }
      18 
      19 inline void init(){
      20     ans=0;
      21     m=200;
      22     for (int i=1; i<=n; i++) y[i]=i;
      23     for (int i=1; i<=n; i++) he[i]=0;
      24 }
      25 
      26 inline void cheight(){
      27     for (int i=1; i<=n; i++) rk [ sa[i] ] = i;
      28     int cnt=0;  //cnt就是lca的长度拉
      29     for (int i=1; i<=n; i++) {
      30         if(cnt<0) cnt=0;
      31         int b = sa[ rk[i]-1 ];  //排在它前一个的那个串的下标
      32         while( a[ b+cnt ] == a[ i+cnt ] ) cnt++;
      33         he[ rk[i] ]=cnt;
      34         //更新答案注意不是一个串内的
      35         if( (i>la && b<=la)||(i<=la && b>la) ) ans=max(ans,cnt);
      36         cnt--;
      37     }
      38 }
      39 
      40 int main(){
      41     //freopen("owo.out","w",stdout);
      42     scanf("%s",in+1);
      43     la = strlen(in+1);
      44     scanf("%s",in+la+2);
      45     in[1+la]='X';  //中间放字符
      46     n=strlen(in+1);
      47     init();
      48     for (int i=1; i<=n; i++) x[i]=a[i]=in[i];
      49     qsort();
      50     for (int l=1; l<n; l<<=1) {  //sa部分
      51         int cnt=0;
      52         for (int i=n-l+1; i<=n; i++) y[++cnt]=i;
      53         for (int i=1; i<=n; i++) if(sa[i]>l) y[++cnt]=sa[i]-l;
      54         qsort();
      55         for (int i=1; i<=n; i++) y[i]=x[i];
      56         x[ sa[1] ]=m=1;
      57         for (int i=2; i<=n; i++) {
      58             if( ( y[ sa[i] ] != y[ sa[i-1] ] )||( y[ sa[i]+l ] != y[ sa[i-1]+l ] ) ) m++;  
      59             x[ sa[i] ]=m;
      60         }
      61     }
      62     cheight();
      63     printf("%d
      ",ans); 
      64     return 0;
      65 }
      (❤ ω ❤)
  • 相关阅读:
    TP第2个项目总结
    Qt编写自定义控件10-云台仪表盘
    Qt编写自定义控件9-导航按钮控件
    Qt编写自定义控件8-动画按钮组控件
    Qt编写自定义控件7-自定义可拖动多边形
    Qt编写自定义控件6-指南针仪表盘
    Qt编写自定义控件5-柱状温度计
    Qt编写自定义控件4-旋转仪表盘
    Qt编写自定义控件3-速度仪表盘
    Qt编写自定义控件2-进度条标尺
  • 原文地址:https://www.cnblogs.com/jiecaoer/p/11609119.html
Copyright © 2011-2022 走看看