BZOJ3676: [Apio2014]回文串(SAM+Manacher/PAM)

Description

考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出 
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最 
大出现值。 

Input

输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。 

Output

输出一个整数,为逝查回文子串的最大出现值。 

Sample Input

【样例输入l】
abacaba
【样例输入2]
www

Sample Output

【样例输出l】
7
【样例输出2]
4

解题思路:

1.Manacher+SAM

首先,是不是有人告诉过你本质不同的回文串有O(n)个,就是在Manacher中学过的。

每次在Manacher扩展f[i]时将其在SAM的Parent树中匹配,就是len*wgt最大值。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 typedef long long lnt;
  5 const int N=600005;
  6 const int M=300005;
  7 struct sant{
  8     int tranc[26];
  9     int len;
 10     int pre;
 11 }s[N];
 12 struct pnt{
 13     int hd;
 14     int fa[17];
 15     int wgt;
 16 }p[N];
 17 int cnt;
 18 int dfn;
 19 int siz;
 20 int fin;
 21 int len,m;
 22 lnt ans;
 23 char tmp[M];
 24 int str[M<<1];
 25 int f[N];
 26 int pos[M<<1];
 27 int endpos[M];
 28 int has[N];
 29 int topo[N];
 30 void Insert(int c)
 31 {
 32     int nwp,nwq,lsp,lsq;
 33     nwp=++siz;
 34     p[nwp].wgt=1;
 35     s[nwp].len=s[fin].len+1;
 36     for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
 37         s[lsp].tranc[c]=nwp;
 38     if(!lsp)
 39         s[nwp].pre=1;
 40     else{
 41         lsq=s[lsp].tranc[c];
 42         if(s[lsq].len==s[lsp].len+1)
 43             s[nwp].pre=lsq;
 44         else{
 45             nwq=++siz;
 46             s[nwq]=s[lsq];
 47             s[nwq].len=s[lsp].len+1;
 48             s[nwp].pre=s[lsq].pre=nwq;
 49             while(s[lsp].tranc[c]==lsq)
 50             {
 51                 s[lsp].tranc[c]=nwq;
 52                 lsp=s[lsp].pre;
 53             }
 54         }
 55     }
 56     fin=nwp;
 57     return ;
 58 }
 59 int check(int l,int r)
 60 {
 61     if(l<1||r>len)
 62         return 0;
 63     int root=endpos[r];
 64     for(int i=16;i>=0;i--)
 65     {
 66         if(s[p[root].fa[i]].len>=r-l+1)
 67             root=p[root].fa[i];
 68     }
 69     ans=std::max(ans,(lnt)(r-l+1)*(lnt)(p[root].wgt));
 70     return (r-l+1)*p[root].wgt;
 71 }
 72 int main()
 73 {
 74     scanf("%s",tmp+1);
 75     fin=++siz;
 76     len=strlen(tmp+1);
 77     for(int i=1;i<=len;i++)
 78     {
 79         Insert(tmp[i]-'a');
 80         endpos[i]=fin;
 81     }
 82     for(int i=1;i<=siz;i++)
 83         has[s[i].len]++;
 84     for(int i=1;i<=siz;i++)
 85         has[i]+=has[i-1];
 86     for(int i=1;i<=siz;i++)
 87         topo[has[s[i].len]--]=i;
 88     for(int i=siz;i;i--)
 89     {
 90         int x=topo[i];
 91         p[s[x].pre].wgt+=p[x].wgt;
 92     }
 93     for(int i=1;i<=siz;i++)
 94     {
 95         int x=topo[i];
 96         p[x].fa[0]=s[x].pre;
 97         p[1].fa[0]=1;
 98         for(int j=1;j<=16;j++)
 99             p[x].fa[j]=p[p[x].fa[j-1]].fa[j-1];
100     }
101     int tmpl=0;
102     str[++tmpl]='*';
103     for(int i=1;i<=len;i++)
104     {
105         str[++tmpl]='#';
106         str[++tmpl]=tmp[i];
107         pos[tmpl]=i;
108     }
109     str[++tmpl]='#';
110     str[++tmpl]='$';
111     int now=0;
112     for(int i=1;i<=tmpl;i++)
113     {
114         f[i]=std::min(f[now]+now-i,f[now*2-i]);
115         f[i]=std::max(f[i],1);
116         check(pos[i-f[i]+2],pos[i+f[i]-2]);
117         while(str[i-f[i]]==str[i+f[i]])
118         {
119             f[i]++;
120             check(pos[i-f[i]+2],pos[i+f[i]-2]);
121         }
122         if(f[now]+now<f[i]+i)
123             now=i;
124     }
125     printf("%lld\n",ans);
126     return 0;
127 }

 2.PAM模板

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 typedef long long lnt;
 5 struct pant{
 6     int tranc[26];
 7     int pre;
 8     int len;
 9     int wgt;
10 };
11 namespace PAM{
12     pant h[1000000];
13     int siz;
14     int fin;
15     void Res(void)
16     {
17         fin=0;
18         siz=1;
19         h[0].pre=h[1].pre=1;
20         h[1].len=-1;
21         return ;
22     }
23     bool mismatch(char *a,int i,int pa)
24     {
25         return a[i-h[pa].len-1]!=a[i];
26     }
27     void Insert(char *a,int i)
28     {
29         int nwp,lsp,mac;
30         lsp=fin;
31         int c=a[i]-'a';
32         while(mismatch(a,i,lsp))
33             lsp=h[lsp].pre;
34         if(!h[lsp].tranc[c])
35         {
36             nwp=++siz;
37             mac=h[lsp].pre;
38             h[nwp].len=h[lsp].len+2;
39             while(mismatch(a,i,mac))
40                 mac=h[mac].pre;
41             h[nwp].pre=h[mac].tranc[c];
42             h[lsp].tranc[c]=nwp;
43         }
44         fin=h[lsp].tranc[c];
45         h[fin].wgt++;
46         return ;
47     }
48     lnt build(void)
49     {
50         lnt ans=0;
51         for(int i=siz;i;i--)
52         {
53             h[h[i].pre].wgt+=h[i].wgt;
54             ans=std::max(ans,(lnt)(h[i].len)*(lnt)(h[i].wgt));
55         }
56         return ans;
57     }
58 }
59 char tmp[1000000];
60 int main()
61 {
62     PAM::Res();
63     scanf("%s",tmp+1);
64     int len=strlen(tmp+1);
65     for(int i=1;i<=len;i++)
66         PAM::Insert(tmp,i);
67     printf("%lld\n",PAM::build());
68     return 0;
69 }

 

posted @ 2018-11-30 20:07  Unstoppable728  阅读(225)  评论(0编辑  收藏  举报