• 2019牛客全国多校训练四 I题 string (SAM+PAM)


    链接:https://ac.nowcoder.com/acm/contest/884/I
    来源:牛客网

    题目描述

    We call a,ba,ba,b non-equivalent if and only if a≠ba eq ba=b and a≠rev(b)a eq rev(b)a=rev(b), where rev(s)rev(s)rev(s) refers to the string obtained by reversing characters of sss, for example rev(abca)=acbarev(abca)=acbarev(abca)=acba.
    There is a string sss consisted of lower-case letters. You need to find some substrings of sss so that any two of them are non-equivalent. Find out what's the largest number of substrings you can choose.

    输入描述:

    A line containing a string sss of lower-case letters.

    输出描述:

    A positive integer - the largest possible number of substrings of sss that are non-equivalent.
    示例1

    输入

    abac

    输出

    8

    说明

    The set of following substrings is such a choice: abac,b,a,ab,aba,bac,ac,cabac,b,a,ab,aba,bac,ac,cabac,b,a,ab,aba,bac,ac,c.

    备注:

    1≤∣s∣≤2×1051 leq |s|leq 2 	imes 10^51s2×105, sss is consisted of lower-case letters.

    题解:

    题目给你一个字符串s,让你求s中的子串组成的最大集合,满足这个集合内的每一个子串str,  str和rev(str)不同时存在{rev(str):表示str反过来}

    思路:就是先用SAM统计出s#rev(s)中不包含 '#'的所有子串ans1; 然后用PAM统计出s中本质不同的子串数量ans2;

    这答案就是(ans1+ans2)/2;

    为什么呢?

    因为在用SAM统计s#rev(s)的时候会把所有字符串统计两边,而本身就是回文串的只会统计一遍。

    参考代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 #define pii pair<int,int>
      5 #define pil pair<int,long long>
      6 const int INF=0x3f3f3f3f;
      7 const ll inf=0x3f3f3f3f3f3f3f3fll;
      8 inline int read()
      9 {
     10     int x=0,f=1;char ch=getchar();
     11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    
     13     return x*f;
     14 }
     15 const int maxn=4e5+10;
     16 const int MAXN=4e5+10; 
     17 char str[maxn];
     18 int s[maxn];
     19 ll ans;
     20 struct SAM{
     21     int l[maxn<<1],fa[maxn<<1],nxt[maxn<<1][30];
     22     int last,cnt;
     23     
     24     void Init()
     25     {
     26         ans=0;last=cnt=1;
     27         l[cnt]=fa[cnt]=0;
     28         memset(nxt[cnt],0,sizeof(nxt[cnt]));        
     29     }
     30     
     31     int NewNode()
     32     {
     33         ++cnt;
     34         memset(nxt[cnt],0,sizeof(nxt[cnt]));
     35         l[cnt]=fa[cnt]=0;
     36         return cnt;    
     37     }
     38     
     39     void Insert(int ch)
     40     {
     41         int np=NewNode(),p=last;
     42         last=np; l[np]=l[p]+1;
     43         while(p&&!nxt[p][ch]) nxt[p][ch]=np,p=fa[p];
     44         if(!p) fa[np]=1;
     45         else
     46         {
     47             int q=nxt[p][ch];
     48             if(l[p]+1==l[q]) fa[np]=q;
     49             else
     50             {
     51                 int nq=NewNode();
     52                 memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
     53                 fa[nq]=fa[q];
     54                 l[nq]=l[p]+1;
     55                 fa[np]=fa[q]=nq;
     56                 while(nxt[p][ch]==q) nxt[p][ch]=nq,p=fa[p];
     57             }    
     58         }    
     59         ans+=1ll*(l[last]-l[fa[last]]);    
     60     }
     61     
     62 }sam;
     63 
     64 struct Palindromic_Tree{
     65     int next[MAXN][26];
     66     int fail[MAXN];
     67     int cnt[MAXN];
     68     int num[MAXN];
     69     int len[MAXN];
     70     int S[MAXN];
     71     int last;
     72     int n;
     73     int p;
     74  
     75     int newnode(int l) 
     76     {
     77         for(int i=0;i<26;++i) next[p][i]=0;
     78         cnt[p]=0;
     79         num[p]=0;
     80         len[p]=l;
     81         return p++;
     82     }
     83  
     84     void Init() 
     85     {
     86         p=0;
     87         newnode( 0);
     88         newnode(-1);
     89         last=0;
     90         n=0;
     91         S[n]=-1;
     92         fail[0]=1;
     93     }
     94  
     95     int get_fail(int x)
     96     {
     97         while(S[n-len[x]-1]!=S[n])x=fail[x] ;
     98         return x ;
     99     }
    100  
    101     void add(int c) 
    102     {
    103         S[++ n]=c;
    104         int cur=get_fail(last) ;
    105         if(!next[cur][c]) 
    106         {
    107             int now=newnode(len[cur]+2) ;
    108             fail[now]=next[get_fail(fail[cur])][c] ;
    109             next[cur][c]=now ;
    110             num[now]=num[fail[now]]+1;
    111         }
    112         last=next[cur][c];
    113         cnt[last]++;
    114     }
    115  
    116     ll count() 
    117     {
    118         ll res=p*1ll;
    119         for(int i=p-1;i>=0;--i) cnt[fail[i]]+=cnt[i];
    120         //for(int i=1;i<=p;++i) res+=cnt[i];
    121         //cout<<"res "<<res<<endl;
    122         return (res-2);
    123     }
    124 } pam;
    125 
    126 int main()
    127 {
    128     scanf("%s",str);
    129     int len=strlen(str);
    130     
    131     sam.Init();
    132     for(int i=0;i<len;++i) sam.Insert(str[i]-'a');
    133     sam.Insert(28);
    134     for(int i=len-1;i>=0;--i) sam.Insert(str[i]-'a');
    135     ans-=1ll*(len+1)*(len+1);
    136     //cout<<"ans "<<ans<<endl;
    137     pam.Init();
    138     for(int i=0;i<len;++i) pam.add(str[i]-'a');
    139     ans=ans+pam.count();
    140     
    141     printf("%lld
    ",(ans/2ll));
    142     
    143     
    144     return 0;    
    145 }
    View Code
     
  • 相关阅读:
    CSS 基础语法
    标签
    HDU 5487 Difference of Languages BFS
    HDU 5473 There was a kingdom 凸包 DP
    HDU 5468 Puzzled Elena 莫比乌斯反演
    BNU 3692 I18n 模拟
    补题列表
    POJ 3241 曼哈顿距离最小生成树 Object Clustering
    UVa 1309 DLX Sudoku
    CodeForces Round #320 Div2
  • 原文地址:https://www.cnblogs.com/csushl/p/11257819.html
Copyright © 2020-2023  润新知