題意:
考慮一個隻包含小寫拉丁字母的字元串s。我們定義s的一個子串t的“出現值”為t在s中的出現次數乘以t的長度。請你求出s的所有回文子串中的最大出現值。
題解:
回文自動機水題,注意插入字元時求出的cnt數組并不是最後的出現次數,而應該還要加上以它為字尾的回文,也就是所有fail指向它的節點的貢獻。
A C AC AC代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 3e5+50;
char s[MAXN];
struct Trie{
int nxt[MAXN][26],fail[MAXN],len[MAXN],cnt[MAXN];
int sz,lst;
inline void Init(){
fail[0] = fail[1] = 1;
len[0] = 0,len[1] = -1;
sz = lst = 1;
s[0] = '#';
}
inline void Insert(char ch,int en){
int root = lst;
while(s[en]!=s[en-len[root]-1]) root = fail[root];
if(!nxt[root][ch-'a']){
len[++sz] = len[root] + 2;
int tmp = fail[root];
while(s[en]!=s[en-len[tmp]-1]) tmp = fail[tmp];
fail[sz] = nxt[tmp][ch-'a'];
nxt[root][ch-'a'] = sz;
}
lst = nxt[root][ch-'a'];
cnt[lst]++;
}
inline void Solve(){
LL res = 0;
for(int i=sz;i>=2;i--) cnt[fail[i]] += cnt[i];
for(int i=2;i<=sz;i++)
res = max(res,1LL*len[i]*cnt[i]);
printf("%lld\n",res);
}
}PAM;
int main(){
scanf("%s",s+1);
PAM.Init();
for(int i=1;s[i];i++) PAM.Insert(s[i],i);
PAM.Solve();
return 0;
}