• 【hdu3948-不同回文串的个数】后缀数组


    题意:求不同回文串的个数 n<=10^5

    题解:

    先按照manacher的构造方法改造一遍串,然后跑一遍manacher。

    如ababa--> $#a#b#a#b#a#@

    然后跑一遍后缀数组。

    对于一个后缀sa[i]~cl(cl为字符串的总长),我们本来是要加上以sa[i]为中心的回文串的个数p[sa[i]]。

    但是这可能有重复!

    我们可以维护一个tmp,也就是上图中蓝色的框。tmp表示以字符sa[i-1]为中心已经被统计过的回文串的个数。

    到了当前的sa[i],tmp=min(tmp,h[i]);

    每次如果p[x]<=tmp,就continue;

    否则,ans+=(p[x]-tmp)/2;(/2是因为有#)

    按照最上面的构造方法,每个最长回文串p[i]必定以#开头和结尾,所以可以直接除以2,可以画个图看看。

     

    一开始以为z的ascll码<=100,get_sa()那里参数小了。。TLE了好几遍才发现。。

     

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 using namespace std;
      6 
      7 const int N=1000010;
      8 int cl,sl,p[N],rk[N],Rs[N],sa[N],wr[N],y[N],h[N];
      9 char c[N],s[N];
     10 
     11 int minn(int x,int y){return x<y ? x:y;}
     12 int maxx(int x,int y){return x>y ? x:y;}
     13 
     14 void get_sa(int m)
     15 {
     16     for(int i=1;i<=cl;i++) rk[i]=c[i];
     17     for(int i=0;i<=m;i++) Rs[i]=0;
     18     for(int i=1;i<=cl;i++) Rs[rk[i]]++;
     19     for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1];
     20     for(int i=cl;i>=1;i--) sa[Rs[rk[i]]--]=i;
     21     
     22     int ln=1,p=0;
     23     while(p<cl)
     24     {
     25         int k=0;
     26         for(int i=cl-ln+1;i<=cl;i++) y[++k]=i;
     27         for(int i=1;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln;
     28         
     29         for(int i=1;i<=cl;i++) wr[i]=rk[y[i]];
     30         for(int i=1;i<=m;i++) Rs[i]=0;
     31         for(int i=1;i<=cl;i++) Rs[wr[i]]++;
     32         for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1];
     33         for(int i=cl;i>=1;i--) sa[Rs[wr[i]]--]=y[i];
     34         
     35         for(int i=1;i<=cl;i++) wr[i]=rk[i];
     36         for(int i=cl+1;i<=cl+ln;i++) wr[i]=0;
     37         p=1;rk[sa[1]]=1;
     38         for(int i=2;i<=cl;i++)
     39         {
     40             if(wr[sa[i]]!=wr[sa[i-1]] || wr[sa[i]+ln]!=wr[sa[i-1]+ln]) p++;
     41             rk[sa[i]]=p;
     42         }
     43         ln*=2,m=p;
     44     }
     45     sa[0]=0;rk[0]=0;
     46 }
     47 
     48 void get_h()
     49 {
     50     int k=0,j;
     51     for(int i=1;i<=cl;i++) if(rk[i]!=1)
     52     {
     53         j=sa[rk[i]-1];
     54         if(k) k--;
     55         while(c[i+k]==c[j+k] && i+k<=cl && j+k<=cl) k++;
     56         h[rk[i]]=k;
     57     }
     58     h[0]=0;
     59 }
     60 
     61 void manacher()
     62 {
     63     int id=0,mx=0;
     64     p[0]=1;
     65     for(int i=1;i<=cl;i++)
     66     {
     67         if(i+p[2*id-i]-1 < mx) p[i]=p[2*id-i];
     68         else
     69         {
     70             p[i]=maxx(0,mx-i+1);
     71             while(c[i+p[i]]==c[i-p[i]] && i+p[i]<=cl && i-p[i]>=1) p[i]++;
     72             if(i+p[i]-1>mx) mx=i+p[i]-1,id=i;
     73         }
     74     }
     75 }
     76 
     77 void solve()
     78 {
     79     int x,tmp=0,ans=0;
     80     for(int i=1;i<=cl;i++)
     81     {
     82         x=sa[i];
     83         tmp=minn(tmp,h[i]);
     84         if(p[x]<=tmp) continue;
     85         ans+=(p[x]-tmp)/2;
     86         tmp=p[x];
     87     }
     88     printf("%d
    ",ans);
     89 }
     90 
     91 int main()
     92 {
     93     freopen("a.in","r",stdin);
     94     // freopen("me.out","w",stdout);
     95     int T;
     96     scanf("%d",&T);
     97     for(int TT=1;TT<=T;TT++)
     98     {
     99         scanf("%s",s+1);
    100         sl=strlen(s+1);
    101         cl=0;
    102         c[++cl]='$';
    103         int i;
    104         for(i=1;i<=sl;i++) 
    105             c[++cl]='#',c[++cl]=s[i];
    106         c[++cl]='#';c[++cl]='@';
    107         // for(int i=1;i<=cl;i++) printf("%c",c[i]);printf("
    ");
    108         // for(int i=1;i<=cl;i++) printf("%d ",p[i]);printf("
    ");
    109         manacher();
    110         get_sa(200);
    111         get_h();
    112         printf("Case #%d: ",TT);
    113         solve();
    114     }
    115     return 0;
    116 }

     

  • 相关阅读:
    数据库应用-java+sqlserver(十)StuInfo
    数据库应用-java+sqlserver(九)StudentMain和StudentManager
    数据库应用-java+sqlserver(八)StoreScore
    数据库应用-java+sqlserver(七)SqlManager
    小学期学习总结二
    小学期学习总结一
    四则运算小程序
    第二小组第七周学习心得
    需求分析
    MSF
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5912592.html
Copyright © 2020-2023  润新知