zoukankan      html  css  js  c++  java
  • HDU 5421 Victor and String (回文自动机)

    题目大意:让你维护一个字符串,支持在开头结尾插入字符,以及查询本质不同的回文串数量以及回文串总数量

    开头结尾都维护一个$last$指针,如果插入新字符后,整个串是一个回文串,就把另一个$last$赋值成当前的$last$

    为什么这样做就是正确的呢?

    首先,对于这道题而言,一个回文串开头/结尾是等价的

    不合并$last$的情况下,在当前方向添加字符不会被另一个方向所影响,就相当于只在末尾加字符

    如果合并了$last$,说明现在另一个方向的开头字符,能和新添加的字符共同产生贡献,所以必须把另一个$last$赋值成当前的$last$,来完成都是在末尾新添加字符的“假象”

    本质不同的回文串数量就是节点个数,回文串总数量就是所有节点在$pre$树中的深度总和*作为回文末尾的次数

    每次$insert$时都更新即可,注意开$longlong$

      1 #include <cmath>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #define N1 200100
      7 #define S1 (N1<<1)
      8 #define ll long long
      9 #define uint unsigned int
     10 #define rint register int 
     11 #define dd double
     12 #define il inline 
     13 #define inf 0x3f3f3f3f
     14 #define idx(X) (X-'a')
     15 using namespace std;
     16 
     17 int gint()
     18 {
     19     int ret=0,fh=1;char c=getchar();
     20     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     21     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     22     return ret*fh;
     23 }
     24 int n,L,R;
     25 namespace PAM{
     26 int trs[N1][26],pre[N1],dep[N1],num[N1];
     27 int lla,rla,tot;ll sum;
     28 void init(){tot=lla=rla=1,dep[1]=-1,pre[0]=pre[1]=1;}
     29 int lchk(char *str,int i,int p){return str[i+dep[p]+1]!=str[i]?1:0;}
     30 int rchk(char *str,int i,int p){return str[i-dep[p]-1]!=str[i]?1:0;}
     31 void Lins(char *str,int i)
     32 {
     33     int p=lla,np,fp,c=idx(str[i]);
     34     while(lchk(str,i,p)) p=pre[p];
     35     if(!trs[p][c])
     36     {
     37         np=++tot;
     38         dep[np]=dep[p]+2;
     39         fp=pre[p];
     40         while(lchk(str,i,fp)) fp=pre[fp];
     41         pre[np]=trs[fp][c];
     42         trs[p][c]=np;
     43         num[np]=num[pre[np]]+1;
     44     }
     45     lla=trs[p][c];
     46     if(dep[trs[p][c]]==R-L+1) rla=lla;
     47     sum+=num[lla];
     48 }
     49 void Rins(char *str,int i)
     50 {
     51     int p=rla,np,fp,c=idx(str[i]);
     52     while(rchk(str,i,p)) p=pre[p];
     53     if(!trs[p][c])
     54     {
     55         np=++tot;
     56         dep[np]=dep[p]+2;
     57         fp=pre[p];
     58         while(rchk(str,i,fp)) fp=pre[fp];
     59         pre[np]=trs[fp][c];
     60         trs[p][c]=np;
     61         num[np]=num[pre[np]]+1;
     62     }
     63     rla=trs[p][c];
     64     if(dep[trs[p][c]]==R-L+1) lla=rla;
     65     sum+=num[rla];
     66 }
     67 void clr()
     68 {
     69     tot++;
     70     memset(trs,0,tot*4*26);
     71     memset(pre,0,tot*4);
     72     memset(dep,0,tot*4);
     73     memset(num,0,tot*4);
     74     tot=lla=rla=0;sum=0;
     75 }
     76 };
     77 char str[N1];
     78 
     79 int main()
     80 {
     81     //freopen("t2.in","r",stdin);
     82     //freopen("a.out","w",stdout);
     83     while(scanf("%d",&n)!=EOF)
     84     {
     85         int fl;L=100001,R=100000;
     86         char tmp[10];
     87         PAM::clr(),PAM::init();
     88         memset(str,0,sizeof(str));
     89         while(n--)
     90         {
     91             scanf("%d",&fl);
     92             if(fl==1){
     93                 scanf("%s",tmp);
     94                 str[--L]=tmp[0];
     95                 PAM::Lins(str,L);
     96             }else if(fl==2){
     97                 scanf("%s",tmp);
     98                 str[++R]=tmp[0];
     99                 PAM::Rins(str,R);
    100             }else if(fl==3){
    101                 printf("%d
    ",PAM::tot-1);
    102             }else if(fl==4){
    103                 printf("%lld
    ",PAM::sum);
    104             }
    105         }
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    2019春第四次课程设计实验报告
    2019春第三次课程设计实验报告
    2019春第二次课程设计实验报告
    2019春第一次课程设计实验报告
    2019春第十二周作业
    2019春第十一周作业
    2019春第十周作业
    2019春第九周作业
    2019春第八周作业
    关于LeetCode解题提升(四)
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10139819.html
Copyright © 2011-2022 走看看