1.kmp
#include<iostream>
using namespace std;
string a,b;
int ne[1000010];
int main()
{
cin>>a>>b;
int n=a.size(),m=b.size();
a=' '+a,b=' '+b;
for(int i=2,j=0;i<=m;i++){
while(j&&b[i]!=b[j+1])j=ne[j];
if(b[i]==b[j+1])j++;
ne[i]=j;
}
for(int i=1,j=0;i<=n;i++){
while(j&&a[i]!=b[j+1])j=ne[j];
if(a[i]==b[j+1])j++;
if(j==m){
printf("%d\n",i-m+1);
j=ne[j];
}
}
for(int i=1;i<=m;i++)printf("%d ",ne[i]);
return 0;
}
2.hash
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int main()
{
int n,q; cin>>n>>q;
string s; cin>>s;
while(q--)
{
string t; cin>>t;
int ok=1,pre=-1;
for(int i=0;i<t.size();i++)
{
if(s.find(t[i],pre+1)==s.npos)
{
ok=0;
break;
}
pre=s.find(t[i],pre+1);
}
if(ok) puts("YES");
else puts("NO");
}
return 0;
}
#include <bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
const int N=2e5+7;
string s1,s2;
int p1[N],p2[N],n;
void manacher(string &s,int p[]){
string str="$#";
for(int i=0;i<n;i++){
// str=str+s[i]+'#';
str+=s[i];
str+='#';
}
int len=str.length();
int mx=0,id=0;
for(int i=1;i<len;i++){
if(i<mx) p[i]=min(mx-i,p[2*id-i]);
else p[i]=1;
while(str[i+p[i]]==str[i-p[i]]) p[i]++;
if(i+p[i]>mx){
mx=i+p[i];
id=i;
}
}
s=str;
}
int main(){
cin>>n;
cin>>s1>>s2;
manacher(s1,p1);
manacher(s2,p2);
int len=s1.length(),ans=1;
for(int i=2;i<len;i++){
int x=max(p1[i],p2[i-2]);
while(s1[i-x]==s2[i-2+x]) x++;
ans=max(ans,x);
}
printf("%d\n",ans-1);
}
#include<bits/stdc++.h>
using namespace std;
#define N 400020
#define LL long long
LL n,q,r[N],s[N],L,R,m,mx,id,ans[N],a[N],b[N],sl[N],sr[N];
vector<LL>dl[N],dr[N];
vector<pair<LL,LL>>ql[N],qr[N];
struct BIT
{
LL t[2][N];
LL lowbit(LL x){return x&(-x);}
void cg(LL o,LL x,LL c){while(x<N)t[o][x]+=c,x+=lowbit(x);}
LL ask(LL o,LL x){LL r=0;while(x)r+=t[o][x],x-=lowbit(x);return r;}
LL ask(LL o,LL l,LL r){return ask(o,r)-ask(o,l-1);}
LL query(LL k,LL l,LL r){return ask(0,l,r)+k*ask(1,l,r);}
}tl,tr;
int main()
{
scanf("%lld%lld",&n,&q);
for(LL i=1;i<=n;i++){
char ch=getchar();
while(ch<'a' || ch>'z')ch=getchar();
s[i*2-1]=ch-'a'+1;
s[i*2]=27;
}
n=n*2-1,s[0]=27;
for(LL i=1;i<=n;i++){
r[i]=1;
if(mx>i)r[i]=min(r[2*id-i],mx-i+1);
while(0<=i-r[i] && i+r[i]<=n+1 && s[i+r[i]]==s[i-r[i]])r[i]++;
if(i+r[i]-1>mx)mx=i+r[i]-1,id=i;
}
for(LL i=1;i<=n;i++){
r[i]=r[i]/2;
if(i&1)a[i]=r[i]-i/2-1;else a[i]=r[i]-i/2;
b[i]=r[i]+i/2-1;
if(a[i]>=0)a[i]=0,tl.cg(1,i,1);
else dl[-a[i]*2].push_back(i),tl.cg(0,i,a[i]);
if(b[i]>=(n+1)/2)b[i]=(n+1)/2,tr.cg(1,i,1);
else dr[b[i]*2].push_back(i),tr.cg(0,i,b[i]);
sl[i]=sl[i-1]+(i&1?i/2+1:i/2);
sr[i]=sr[i-1]+(1-i/2);
}
for(LL i=1;i<=q;i++){
scanf("%lld%lld",&L,&R);
m=L+R-1,L=L*2-1,R=R*2-1;
ans[i]+=sl[m]-sl[L-1]+sr[R]-sr[m];
ql[L].push_back(make_pair(i,m));
qr[R].push_back(make_pair(i,m));
}
for(LL i=1;i<=n;i++){
for(auto j:dl[i])tl.cg(0,j,-a[j]),tl.cg(1,j,1);
for(auto pi:ql[i])ans[pi.first]+=tl.query(-i/2,i,pi.second);
}
for(LL i=n;i>=1;i--){
for(auto j:dr[i])tr.cg(0,j,-b[j]),tr.cg(1,j,1);
for(auto pi:qr[i])ans[pi.first]+=tr.query(i/2,pi.second+1,i);
}
for(LL i=1;i<=q;i++)printf("%lld\n",ans[i]);
}
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
char s[N];
int len[N], cnt[N][2], fail[N];
int t[N][26], last = 0, tot = 1;
int getfail(int u, int p)
{
while (s[p - len[u] - 1] != s[p]) u = fail[u];
return u;
}
void insert(int c, int p, int id)
{
int u = getfail(last, p);
if (!t[u][c])
{
fail[++tot] = t[getfail(fail[u], p)][c];
len[t[u][c] = tot] = len[u] + 2;
}
cnt[last = t[u][c]][id]++;
}
int main()
{
fail[0] = 1, s[0] = '!', len[1] = -1;
scanf("%s", s + 1);
for (int i = 1; s[i]; i++) insert(s[i] - 'A', i, 0);
scanf("%s", s + 1), last = 0;
for (int i = 1; s[i]; i++) insert(s[i] - 'A', i, 1);
for (int i = tot; i > 1; i--)
cnt[fail[i]][0] += cnt[i][0], cnt[fail[i]][1] += cnt[i][1];
long long ans = 0;
for (int i = 2; i <= tot; i++) ans += 1ll * cnt[i][0] * cnt[i][1];
cout << ans;
return 0;
}
3.border树,trie树
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int n,idx;
bool cnt[300010];
string s[30010];
int tr[300010][26];
vector<string>q;
void insert(string s)
{
int u=0;
for(int i=0;i<s.size();i++){
int p=s[i]-'a';
if(!tr[u][p])tr[u][p]=++idx;
u=tr[u][p];
}
cnt[u]=true;
}
bool check(string s)
{
int u=0;
int in[26]={0};
vector<int>edge[26];
for(int i=0;i<s.size();i++){
if(cnt[u])return false;
int p=s[i]-'a';
for(int j=0;j<26;j++){
if(p!=j&&tr[u][j]){
in[j]++;
edge[p].push_back(j);
}
}
u=tr[u][p];
}
queue<int>Q;
for(int i=0;i<26;i++){
if(in[i]==0)Q.push(i);
}
while(Q.size()){
int t=Q.front();
Q.pop();
for(auto c:edge[t]){
in[c]--;
if(in[c]==0)Q.push(c);
}
}
for(int i=0;i<26;i++){
if(in[i])return false;
}
return true;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i];
insert(s[i]);
}
for(int i=1;i<=n;i++){
if(check(s[i]))q.push_back(s[i]);
}
cout<<(int)q.size()<<endl;
for(auto c:q)cout<<c<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N = 3e6+50;
int ch[N][2],tot;
void insert(int x){
int u=0;
for(int i=30;~i;i--){
int v=(x>>i)&1;
if(!ch[u][v]) ch[u][v]=++tot;
u=ch[u][v];
}
}
int query(int x){
int res=0,u=0;
for(int i=30;~i;i--){
int v=(x>>i)&1;
if(ch[u][v^1]) v^=1,res|=1<<i;
u=ch[u][v];
}
return res;
}
signed main(void){
ios::sync_with_stdio(false);cin.tie(0);
int n,res=0,x;
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
res=max(res,query(x));
insert(x);
}
cout<<res;
}
#include<bits/stdc++.h>
using namespace std;
int t[100010*32][2],idx,cnt[100010*32],id;
void insert(int x){
int now=0;
for(int i=31;i>=0;i--){
if(!t[now][x>>i&1])t[now][x>>i&1]=++idx;
now=t[now][x>>i&1];
}
cnt[now]=++id;
}
pair<int,int>ch(int x){
int ans=0,now=0;
for(int i=31;i>=0;i--){
int num=x>>i&1;
if(t[now][!num])now=t[now][!num],ans+=1<<i;
else now=t[now][num];
}
return {ans,cnt[now]};
}
int a[100100];
int main(){
int n,ans=-1,l,r;
cin>>n;
insert(0);
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]^=a[i-1];
auto [x,y]=ch(a[i]);
if(x>ans){
ans=x;
l=y,r=i;
}
insert(a[i]);
}
cout<<ans<<" "<<l<<" "<<r<<endl;
return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
const int N=6e5+5,M=N*25,pos=23;
int n,m;
int s[N];
int tr[M][2],max_id[M];
int root[N],idx;
void insert(int k,int p,int q)
{
for(int i=pos;i>=0;i--)
{
int u=s[k]>>i&1;
if(p)
tr[q][u^1]=tr[p][u^1];
tr[q][u]=++idx;
p=tr[p][u],q=tr[q][u];
max_id[q]=k;
}
}
int query(int root,int c,int l)
{
int p=root;
for(int i=pos;i>=0;i--)
{
int u=c>>i&1;
if(max_id[tr[p][u^1]]>=l)
p=tr[p][u^1];
else
p=tr[p][u];
}
return c^s[max_id[p]];
}
int main()
{
cin>>n>>m;
max_id[0]=-1;
root[0]=++idx;
insert(0,0,root[0]);
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
s[i]=s[i-1]^x;
root[i]=++idx;
insert(i,root[i-1],root[i]);
}
char op;
int l,r,x;
while(m--)
{
cin>>op;
if(op=='A')
{
cin>>x;
n++;
s[n]=s[n-1]^x;
root[n]=++idx;
insert(n,root[n-1],root[n]);
}
else
{
cin>>l>>r>>x;
cout<<query(root[r-1],s[n]^x,l-1)<<endl;
}
}
return 0;
}
#include<iostream>
using namespace std;
const int N=2e6;
char str[N];
int n,k,nx[N];
int sz[N];
int main()
{
scanf("%d%d",&n,&k);
scanf("%s",str+1);
for(int i=2,j=0;i<=n;i++)
{
while(j&&str[j+1]!=str[i]) j=nx[j];
if(str[j+1]==str[i]) j++;
nx[i]=j;
}
for(int i=n;i>=1;i--)
{
sz[i]++;
sz[nx[i]]+=sz[i];
}
int u=n;
while(sz[u]<k)
{
u=nx[u];
}
if(u==0) cout<<"-1"<<endl;
else for(int i=1;i<=u;i++) cout<<str[i];
return 0;
}
4. ac自动机
#include<bits/stdc++.h>
using namespace std;
template<typename T>std::istream&operator>>(std::istream&is,std::vector<T>&t){for(auto&x:t)is>>x;return is;}
template<typename T>std::ostream&operator<<(std::ostream&os,const std::vector<T>&t){for(int i=0;i<t.size();++i)os<<t[i]<<" \n"[i==t.size()-1];return os;}
#define INF 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl "\n"
#define rep(pigstar,a,b) for (int pigstar = (a); pigstar <= (b); pigstar ++)
#define per(pigstar,a,b) for (int pigstar = (a); pigstar >= (b); pigstar --)
#define cinint(pigstar,a,b) for (int i = (a); i <= (b); i ++) cin >> pigstar[i];
#define coutint(pigstar,a,b) for (int i = (a); i <= (b); i ++) cout << pigstar[i] << " \n"[i==b]
#define all(pigstar) pigstar.begin(),pigstar.end()
#define rvs(pigstar) reverse(pigstar.begin(),pigstar.end())
#define PII array<int, 2>
#define VI vector<int>
#define VPII vector<PII>
#define pb push_back
#define SZ(pigstar) ((int)(pigstar).size())
#define MP make_pair
#define x first
#define y second
#define CN puts("NO")
#define CY puts("YES")
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
//----------------debug---------------//
#define debug(args...) { string _s = #args; auto end_pos = remove(_s.begin(), _s.end(), ' '); _s.erase(end_pos, _s.end()); replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); cout << "\n";}
void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
cerr << (*it) << " = " << a << " ";
err(++it, args...);
}
//----------------debug---------------//
//----------------hash_map---------------//
#include <functional>
template <typename T>
inline void hash_combine(std::size_t &seed, const T &val) {
seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
// auxiliary generic functions to create a hash value using a seed
template <typename T>
inline void hash_val(std::size_t &seed, const T &val) {
hash_combine(seed, val);
}
template <typename T, typename... Types>
inline void hash_val(std::size_t &seed, const T &val, const Types &... args) {
hash_combine(seed, val);
hash_val(seed, args...);
}
template <typename... Types>
inline std::size_t hash_val(const Types &... args) {
std::size_t seed = 0;
hash_val(seed, args...);
return seed;
}
struct pair_hash {
template <class T1, class T2>
std::size_t operator()(const std::pair<T1, T2> &p) const {
return hash_val(p.first, p.second);
}
};
struct int_hash {
static uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(const uint64_t x) const {
static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
//unordered_map<PII,int,pair_hash> mp1
// unordered_map<int,int,int_hash> mp2
//----------------hash_map---------------//
const int maxn = 2e6+7;
const int mod = 1e9+7;
const double eps = 1e-7;
int qmi(int a, int k, int p){int res = 1;while (k){if (k & 1) res = (ll)res * a % p;a = (ll)a * a % p;k >>= 1;}return res;}
int qpow(int a,int b){int res = 1;while(b){if(b&1) res *= a;b>>=1;a*=a;}return res;}
int mo(int x,int p){return x = ((x%p)+p)%p;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lowbit(int x) { return (-x)&x; }
int fac[maxn], invfac[maxn], __ = [] {
fac[0] = 1;
for (int i = 1; i < maxn; i ++) {
fac[i] = (fac[i - 1] * i) % mod;
}
invfac[maxn - 1] = qmi(fac[maxn - 1], mod - 2, mod);
for (int i = maxn - 1; i; i --) {
invfac[i - 1] = (invfac[i] * i) % mod;
}
return 0;
}();
int C (int n, int m) {
return ((fac[n] * invfac[m]) % mod * invfac[n - m]) % mod;
}
int dx[] = {0,0,1,-1}, dy[] = {1,-1,0,0};
int T = 1,N,M,K,Q;
// unordered_map<PII,int,pair_hash> mp;
// unordered_map<int,int,int_hash> mp2;
struct AC_Automaton{
int nxt[maxn][26], fail[maxn], cnt[maxn], id[maxn];
int root, idx;
vector<int>g[maxn];//用来保存最后的fail的树
void clear(){
memset(nxt[0],0,sizeof(nxt[0]));
root = idx = 0;
}
int newnode(){
idx++; memset(nxt[idx],0,sizeof(nxt[idx]));
return idx;
}
int insert(int pre, int ch){
return nxt[pre][ch]?nxt[pre][ch]: nxt[pre][ch] = newnode();
}
int insert(string s, int u){
int now = root;
for(char &c : s){
now = insert(now, c-'a');
}
return id[u] = now;
}
void build(){
fail[root] = root;
queue<int>q;
for(int i = 0 ; i < 26 ; i ++) {
if(nxt[0][i]) {
g[0].push_back(nxt[0][i]);
q.push(nxt[0][i]);
}
}
while(!q.empty()){
int h = q.front(); q.pop();
for(int i = 0 ; i < 26 ; i ++){
if(!nxt[h][i]){
nxt[h][i] = nxt[fail[h]][i];
}
else{
int tmp = nxt[h][i];
fail[tmp] = nxt[fail[h]][i];
g[fail[tmp]].push_back(tmp);
q.push(tmp);
}
}
}
}
void query(string &s){
int now = root;
for(char &c : s){
now = nxt[now][c-'a'];
cnt[now]++;
}
get_ans();
}
void get_ans() {
for (int i = 0; i < 26; i++)
if (nxt[0][i])dfs(nxt[0][i]);
}
void dfs(int u) {
for (int v : g[u]) {
dfs(v);
cnt[u] += cnt[v];
}
}
}ac;
string s,t;
void solve(){
cin >> N;
for (int i = 0; i < N; i ++) {
cin >> t;
ac.insert(t,i);
}
ac.build();
cin >> s;
ac.query(s);
rep(i,0,N-1) {
cout << ac.cnt[ac.id[i]] << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);
cout.setf(ios::fixed);cout.precision(16);
// cin >> T;
// fact_init();
while (T --) {
solve();
}
return (0-0); //<3
}
//最简ac自动机
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int N=2e5+3;
int t[N][26],cnt,fail[N],stop[N],ans[N],id[N];
void insert(string s,int p){
int x=0;
for(auto& i:s){
int k=i-'a';
if(!t[x][k])t[x][k]=++cnt;
x=t[x][k];
}
stop[x]++;id[p]=x;
}
int q[N],top=0,low=1;
void bfs(){
rep(i,0,25)if(t[0][i])q[++top]=t[0][i];
while(low<=top){
int x=q[low++];
rep(i,0,25){
int & son=t[x][i];
if(son){
fail[son]=t[fail[x]][i];q[++top]=son;
}else son=t[fail[x]][i];
}
}
}
void query(string s){
int x=0;
for(auto& i:s){
int k=i-'a';
x=t[x][k];ans[x]++;
}
for(int i=top;i>0;i--){
ans[fail[q[i]]]+=ans[q[i]];
}
}
int main(){
int n;cin>>n;
string s;
rep(i,1,n)cin>>s,insert(s,i);
bfs();cin>>s;query(s);
rep(i,1,n)cout<<ans[id[i]]<<endl;
}
5.pam manacher
//#只会是奇数,字母只会是偶数
//所以两者的长度都是减去1,没错了
#include <bits/stdc++.h>
using namespace std;
const int M=2e5+10;
int cnt=1;
char s[M];
int p[M],L[M],R[M];
void manacher(string t) {
s[0]='@';
s[1]='#';
for(auto i:t)s[++cnt]=i,s[++cnt]='#';
for(int i=1,mid=0,r=0;i<=cnt;i++) {
if(i<=r)p[i]=min(p[2*mid-i],r-i+1);
while(s[i-p[i]]==s[i+p[i]])p[i]++;
if(i+p[i]>r)r=i+p[i]-1,mid=i;
L[i+p[i]-1]=max(L[i+p[i]-1],p[i]-1);
R[i-p[i]+1]=max(R[i-p[i]+1],p[i]-1);
}
}
int main() {
string t;cin>>t;
manacher(t);
for(int i=3;i<=cnt;i+=2)R[i]=max(R[i],R[i-2]-2);
for(int i=cnt;i>=1;i-=2)L[i]=max(L[i],L[i+2]-2);
int ans=0;
for(int i=3;i<cnt;i++)ans=max(ans,L[i]+R[i]);
cout<<ans;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
char s[1000010]={'?'};
int p[1000010],n,ans;
void manacher(char *s,int n){
for(int c=0,mx=0,i=1;i<=n;i++){
p[i]=i<mx?min(p[2*c-i],mx-i):1;
while(s[i+p[i]]==s[i-p[i]])++p[i];
if(i+p[i]>mx){
if(i&1)for(int j=max(mx,i+4);j<i+p[i];j++)
if(!(j-i&3) && p[i-(j-i)/2]>(j-i)/2)ans=max(ans,j-i);
mx=i+p[i],c=i;
}
}
}
int main(){
scanf("%d %s",&n,s+1);
for(int i=n;i;i--)s[i*2+1]='#',s[i*2]=s[i];s[1]='#';
manacher(s,2*n+1);
printf("%d\n",ans);
return 0;
}
// o队的代码,我改了改
#include <bits/stdc++.h>
using namespace std;
#define fo(i,j,k) for(int i=(j),end_i=(k);i<=end_i;i++)
#define ff(i,j,k) for(int i=(j),end_i=(k);i< end_i;i++)
#define fd(i,j,k) for(int i=(j),end_i=(k);i>=end_i;i--)
#define DEBUG(x) cerr<<#x<<"="<<x<<endl
#define DEBUGv(x) cerr<<#x<<" : "; ff(i,0,(x).size()) cerr<<(x)[i]<<(i==(x).size()-1?'\n':' ')
#define all(x) (x).begin(),(x).end()
#define cle(x) memset(x,0,sizeof(x))
#define lowbit(x) ((x)&-(x))
#define VI vector<int>
#define ll long long
#define ull unsigned ll
#define lll __int128
#define db double
#define lb long db
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define endl "\n"
template<class T>inline void read(T &x) {
x=0; char ch=getchar(); bool f=0;
for(;ch<'0'||ch>'9';ch=getchar()) f|=(ch=='-');
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+(ch^48);
if(f) x=-x;
}
template<class T, class... V>
inline void read(T &a, V&... b){read(a); read(b...);}
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 5e5 + 5;
const int S = 26;
namespace PAM {
int n,s[N],num[N],p,las,nex[N][S],fail[N],len[N],sz[N];
ll ans;
int cnt[N];
int f[N][19];
int ans2;
void add(int x, int y) {
cnt[y] = cnt[x];
int cha=len[y]-len[x];
if(len[y]%4==0 && (len[y]/2)%cha==0 && cha<=len[y]/2 && y>=3)
{
cnt[y]++;
ans2=max(len[y],ans2);
}
}
void init() {
ans = 0;
ans2 = 0;
for(int i=0;i<=n;i++) s[i]=0;
for(int i=1;i<=p;i++) len[i]=fail[i]=sz[i]=0,memset(nex[i],0,sizeof(nex[i])),memset(f[i],0,sizeof(f[i])), cnt[i]=0;
s[n=0]=len[p=2]=-1;
fail[las=1]=fail[2]=2;
len[1]=0;
add(2,0);
add(2,1);
}
int getfail(int x) {for(;s[n-1-len[x]]!=s[n];x=fail[x]); return x;}
void update(int x) {
ans += cnt[x];
}
void add(int c) {
s[++n]=c;
int cur=getfail(las);
if(!nex[cur][c]) {
len[++p]=len[cur]+2;
fail[p]=nex[getfail(fail[cur])][c];
if(!fail[p]) fail[p]=1;
nex[cur][c]=p;
add(fail[p], p);
}
las=nex[cur][c];
sz[las]++;
update(las);
}
ll ask() {
return ans2;
}
}
char s[N];
void Solve() {
PAM::init();
scanf("%s", s + 1);
int n = strlen(s + 1);
fo(i,1,n) {
PAM::add(s[i] - 'a');
}
printf("%d\n", PAM::ask());
}
int main() {
int T = 1;
int n;
read(n);
for(;T--;) Solve();
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
typedef long long ll;
char s[N];
int n,last,len[N];
int now,tot=1,fail[N],cnt[N],trie[N][30];
int getfail(int u,int p)
{
while(p-len[u]-1<=0||s[p-len[u]-1]!=s[p]) u=fail[u];
return u;
}
void insert(char c,int id)
{
int p=getfail(now,id);
if(!trie[p][c-'a'])
{
fail[++tot]=trie[getfail(fail[p],id)][c-'a'];
trie[p][c-'a']=tot;
len[tot]=len[p]+2;
}
now=trie[p][c-'a'];
cnt[now]++;
}
int main()
{
cin>>n>>s+1;
fail[0]=1;
len[1]=-1;
for(int i=1;i<=n;i++) insert(s[i],i);
for(int i=tot;i>=1;i--) cnt[fail[i]]+=cnt[i];
ll ans=0;
for(int i=1;i<=tot;i++)
{
ans=max(ans,1ll*cnt[i]*len[i]);
}
cout<<ans<<endl;
}
#include <bits/stdc++.h>
using namespace std;
#define fo(i,j,k) for(int i=(j),end_i=(k);i<=end_i;i++)
#define ff(i,j,k) for(int i=(j),end_i=(k);i< end_i;i++)
#define fd(i,j,k) for(int i=(j),end_i=(k);i>=end_i;i--)
#define DEBUG(x) cerr<<#x<<"="<<x<<endl
#define DEBUGv(x) cerr<<#x<<" : "; ff(i,0,(x).size()) cerr<<(x)[i]<<(i==(x).size()-1?'\n':' ')
#define all(x) (x).begin(),(x).end()
#define cle(x) memset(x,0,sizeof(x))
#define lowbit(x) ((x)&-(x))
#define VI vector<int>
#define ll long long
#define ull unsigned ll
#define lll __int128
#define db double
#define lb long db
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define endl "\n"
template<class T>inline void read(T &x) {
x=0; char ch=getchar(); bool f=0;
for(;ch<'0'||ch>'9';ch=getchar()) f|=(ch=='-');
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+(ch^48);
if(f) x=-x;
}
template<class T, class... V>
inline void read(T &a, V&... b){read(a); read(b...);}
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 3e5 + 5;
const int S = 26;
namespace PAM {
int n,s[N],num[N],p,las,nex[N][S],fail[N],len[N],sz[N];
ll ans;
void init() {
ll ans=0;
for(int i=0;i<=n;i++) s[i]=0;
for(int i=1;i<=p;i++) len[i]=fail[i]=sz[i]=0,memset(nex[i],0,sizeof(nex[i]));
s[n=0]=len[p=2]=-1;
fail[las=1]=fail[2]=2;
len[1]=0;
}
int getfail(int x) {for(;s[n-1-len[x]]!=s[n];x=fail[x]); return x;}
void add(int c) {
s[++n]=c;
int cur=getfail(las);
if(!nex[cur][c]) {
len[++p]=len[cur]+2;
fail[p]=nex[getfail(fail[cur])][c];
if(!fail[p]) fail[p]=1;
nex[cur][c]=p;
}
las=nex[cur][c];
sz[las]++;
//cout<<las<<' '<<sz[las]<<' '<<len[las]<<endl;
//ans=max(ans,1ll*sz[las]*len[las]);
}
void cnt()
{
for(int i=p;i>=3;i--)
{
sz[fail[i]]+=sz[i];
ans=max(ans,1ll*sz[i]*len[i]);
}
}
ll ask()
{
return ans;
}
}
char s[N];
void Solve() {
PAM::init();
scanf("%s", s + 1);
int n = strlen(s + 1);
fo(i,1,n) {
PAM::add(s[i] - 'a');
}
PAM::cnt();
//printf("%lld%c", PAM::ask(),(i==n)?'\n':' ');
printf("%lld\n",PAM::ask());
}
int main() {
int T = 1;
int n;
read(n);
for(;T--;) Solve();
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
char s[N];
int len[N], cnt[N], fail[N];
int t[N][26], last = 0, tot = 1;
int getfail(int u, int p)
{
while (s[p - len[u] - 1] != s[p]) u = fail[u];
return u;
}
int f[N];
void insert(int c, int p)
{
int u = getfail(last, p);
if (!t[u][c])
{
fail[++tot] = t[getfail(fail[u], p)][c];
len[t[u][c] = tot] = len[u] + 2;
f[tot] = f[u] | (1 << c);
}
cnt[last = t[u][c]]++;
}
int calc(int x)
{
int ans = 0;
while (x) ans += x & 1, x >>= 1;
return ans;
}
int main()
{
fail[0] = 1, s[0] = '!', len[1] = -1;
scanf("%s", s + 1);
for (int i = 1; s[i]; i++) insert(s[i] - 'a', i);
for (int i = tot; i > 1; i--) cnt[fail[i]] += cnt[i];
long long ans = 0;
for (int i = 2; i <= tot; i++) ans += 1ll * calc(f[i]) * cnt[i];
cout << ans;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define fo(i,j,k) for(int i=(j),end_i=(k);i<=end_i;i++)
#define ff(i,j,k) for(int i=(j),end_i=(k);i< end_i;i++)
#define fd(i,j,k) for(int i=(j),end_i=(k);i>=end_i;i--)
#define DEBUG(x) cerr<<#x<<"="<<x<<endl
#define DEBUGv(x) cerr<<#x<<" : "; ff(i,0,(x).size()) cerr<<(x)[i]<<(i==(x).size()-1?'\n':' ')
#define all(x) (x).begin(),(x).end()
#define cle(x) memset(x,0,sizeof(x))
#define lowbit(x) ((x)&-(x))
#define VI vector<int>
#define ll long long
#define ull unsigned ll
#define lll __int128
#define db double
#define lb long db
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define endl "\n"
template<class T>inline void read(T &x) {
x=0; char ch=getchar(); bool f=0;
for(;ch<'0'||ch>'9';ch=getchar()) f|=(ch=='-');
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+(ch^48);
if(f) x=-x;
}
template<class T, class... V>
inline void read(T &a, V&... b){read(a); read(b...);}
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 3e5 + 5;
const int S = 26;
namespace PAM {
int n,s[N],num[N],p,las,nex[N][S],fail[N],len[N],sz[N];
int yh[N][30],cnt[N];
ll ans;
void init() {
ll ans=0;
for(int i=0;i<=n;i++) s[i]=0;
for(int i=1;i<=p;i++) len[i]=fail[i]=sz[i]=0,memset(nex[i],0,sizeof(nex[i]));
s[n=0]=len[p=2]=-1;
fail[las=1]=fail[2]=2;
len[1]=0;
}
int getfail(int x) {for(;s[n-1-len[x]]!=s[n];x=fail[x]); return x;}
void yh1(int x,int y,int c)
{
for(int i=0;i<=26;i++)
yh[y][i]=yh[x][i];
cnt[y]=cnt[x];
if(yh[y][c]==0)
{
cnt[y]++;
yh[y][c]=1;
}
}
void add(int c) {
s[++n]=c;
int cur=getfail(las);
if(!nex[cur][c]) {
len[++p]=len[cur]+2;
fail[p]=nex[getfail(fail[cur])][c];
if(!fail[p]) fail[p]=1;
nex[cur][c]=p;
yh1(cur,p,c);
}
las=nex[cur][c];
sz[las]++;
}
void cnt1()
{
for(int i=p;i>=3;i--)
{
sz[fail[i]]+=sz[i];
ans+=1ll*sz[i]*cnt[i];
}
}
ll ask()
{
return ans;
}
}
char s[N];
void Solve() {
PAM::init();
scanf("%s", s + 1);
int n = strlen(s + 1);
fo(i,1,n) {
PAM::add(s[i] - 'a');
}
PAM::cnt1();
//printf("%lld%c", PAM::ask(),(i==n)?'\n':' ');
printf("%lld\n",PAM::ask());
}
int main() {
int T = 1;
int n;
//read(n);
for(;T--;) Solve();
return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6+10,MOD=1e9+7;
int n,f[N],i,ft[N];
char s[N];
int tr[N][26],fail[N],len[N],g[N],diff[N],slink[N];
int getfail(int u){
while(i-1-len[u]<=0||s[i-1-len[u]]!=s[i])u=fail[u];
return u;
}
void work(){
for(int i = 1;i<=n;++i)f[i]=ft[i],ft[i]=0;
for(int i = 0;i<=n+5;++i)memset(tr[i],0,sizeof tr[i]),g[i]=0;
fail[0]=1,len[1]=-1;
int cnt=1,lst = 0;
for(i = 1;i<=n;++i){
int t=s[i]-'a';
lst=getfail(lst);
if(!tr[lst][t]){
fail[++cnt]=tr[getfail(fail[lst])][t];
tr[lst][t]=cnt;
len[cnt]=len[lst]+2;
diff[cnt]=len[cnt]-len[fail[cnt]];
if(fail[cnt]<=1){
diff[cnt]=-233;
}
if(diff[cnt]!=diff[fail[cnt]]){
slink[cnt]=cnt;
}
else slink[cnt]=slink[fail[cnt]];
}
lst=tr[lst][t];
int u=lst;
ft[i]=ft[i-1];
while(u>1){
if(slink[u]!=u){
g[u]=max(g[fail[u]]+diff[u],f[i-len[slink[u]]]+len[slink[u]]);
}
else{
g[u]=f[i-len[slink[u]]]+len[slink[u]];
}
ft[i]=max(ft[i],g[u]);
u=fail[slink[u]];
}
// cout<<ft[i]<<'\n';
}
}
void solve(){
scanf("%s",s+1);
n=strlen(s+1);
for(int i = 1;i<=n;++i)ft[i]=0;
work();
work();
work();
cout<<ft[n]<<'\n';
}
int main(){
// freopen("a.txt","r",stdin);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
6.sa
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int rk[N],sa[N],c[N],id[N],px[N],ht[N];
char s[N];
bool cmp(int x,int y,int w){
return id[x]==id[y]&&id[x+w]==id[y+w];
}
void init(int n){
int m=26,p,k,i;
for(i=0;i<=m;i++) c[i]=0;
for(i=1;i<=n;i++) c[rk[i]=(s[i]-'a'+1)]++;
for(i=1;i<=m;i++) c[i]+=c[i-1];
for(i=n;i>=1;i--) sa[c[rk[i]]--]=i;//
for(k=1;;k<<=1,m=p){
for(p=0,i=n;i>n-k;--i)id[++p]=i;
for(i=1;i<=n;i++)
if(sa[i]>k)id[++p]=sa[i]-k;
//将所有的
for(i=0;i<=m;i++)c[i]=0;
for(i=1;i<=n;++i) ++c[px[i] = rk[id[i]]];
for(i=1;i<=m;++i) c[i] += c[i-1];
for(i=n;i>=1;--i) sa[c[px[i]]--] = id[i];
for(i=0;i<=n;++i) swap(rk[i],id[i]);
for(p=0,i=1;i<=n;++i)
rk[sa[i]]=cmp(sa[i],sa[i-1],k) ? p : ++p;
if(p>=n) break;
}
for(int i=0;i<=n;i++)id[i]=0;
for(int i=1,k=0;i<=n;i++){
if(k)k--;
int j=sa[rk[i]-1];
while(s[i+k]==s[j+k])k++;
ht[rk[i]] = k;
}
}
int main(){
int t;
cin>>t;
while(t--){
scanf("%s",s+1);
int n=strlen(s+1);
init(n);
for(int i=1;i<=n;i++)cout<<sa[i]<<' ';
puts("");
for(int i=1;i<=n;i++)cout<<ht[i]<<' ';
puts("");
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int const N=1000000+3;
struct node
{
int ch[26];
int len,fa;
node()
{
memset(ch,0,sizeof(ch));
len=0;
}
} a[N<<1];
int ls=1,tot=1;
void add(int c)
{
int p=ls;
int np=ls=++tot;
a[np].len=a[p].len+1;
for(; p&&!a[p].ch[c]; p=a[p].fa) a[p].ch[c]=np;
if(!p) a[np].fa=1;
else
{
int q=a[p].ch[c];
if(a[q].len==a[p].len+1) a[np].fa=q;
else
{
int nq=++tot;
a[nq]=a[q];
a[nq].len=a[p].len+1;
a[q].fa=a[np].fa=nq;
for(; p && a[p].ch[c]==q; p=a[p].fa) a[p].ch[c]=nq;
}
}
}
char s[N<<1];
int len;
int main()
{
scanf("%s",s);
for(int i=0; s[i]; i++) add(s[i]-'a');
long long ans=0;
for(int i=1; i<=tot; i++) ans+=a[i].len-a[a[i].fa].len;
printf("%lld\n",ans);
return 0;
}
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct node {
int fa, len;
int son[31];
node() {
fa = len = 0;
memset(son, 0, sizeof(son));
}
}d[500001*2];
char a[500001], b[500001];
int an, bn, tot, lst, ans;
void SAM_build(int now) {
int p = lst;
int np = ++tot;
lst = np;
d[np].len = d[p].len + 1;
for (; p && !d[p].son[now]; p = d[p].fa)
d[p].son[now] = np;
if (!p) d[np].fa = 1;
else {
int q = d[p].son[now];
if (d[q].len == d[p].len + 1) d[np].fa = q;
else {
int nq = ++tot;
d[nq] = d[q];
d[nq].len = d[p].len + 1;
d[q].fa = nq;
d[np].fa = nq;
for (; p && d[p].son[now] == q; p = d[p].fa)
d[p].son[now] = nq;
}
}
}
void work() {
int now = 1, nowd = 0;
for (int i = 1; i <= bn; i++) {
int go = b[i] - 'a';
if (d[now].son[go]) {
nowd++;
now = d[now].son[go];
ans = max(ans, nowd);
continue;
}
while (now && !d[now].son[go]) now = d[now].fa;
if (!now) {
nowd = 0;
now = 1;
}
else {
nowd = d[now].len + 1;
now = d[now].son[go];
}
ans = max(ans, nowd);
}
}
int main() {
scanf("%s\n%s", a + 1, b + 1);
an = strlen(a + 1);
bn = strlen(b + 1);
tot = 1;
lst = 1;
for (int i = 1; i <= an; i++)
SAM_build(a[i] - 'a');
work();
printf("%d", ans);
return 0;
}
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<cstring>
#include<vector>
#include<iostream>
#include<string>
#define Inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int MAXX=1000005;
struct SamNode{
int ch[26];
int len,fa;
bool vis[2];
SamNode(){memset(ch,0,sizeof(ch));len=0;vis[0]=vis[1]=false;}
}sam[MAXX<<1];
int las=1,sam_cnt=1;
void add(int c,int jj){
int p=las;int np=las=++sam_cnt;
// num[np]=1LL;//此行为计数用,标记出现过几次
sam[np].len=sam[p].len+1;
for(;p&&!sam[p].ch[c];p=sam[p].fa) sam[p].ch[c]=np;
if(!p) sam[np].fa=1;
else{
int q=sam[p].ch[c];
if(sam[q].len==sam[p].len+1) sam[np].fa=q;
else{
int nq=++sam_cnt;sam[nq]=sam[q];
sam[nq].len=sam[p].len+1;
sam[q].fa=sam[np].fa=nq;
for(;p&&sam[p].ch[c]==q;p=sam[p].fa) sam[p].ch[c]=nq;
}
}
for(;np&&!sam[np].vis[jj];np=sam[np].fa) sam[np].vis[jj]=true;
}
int n;
char s[MAXX];
LL ans=0;
inline void solve(){
for(int i=1;i<=2;++i){
scanf("%s",s+1);getchar();
n=strlen(s+1);
las=1;
for(int j=1;j<=n;++j)
add(s[j]-'a',i-1);
}
for(int i=1;i<=sam_cnt;++i)
if(sam[i].vis[0]&&sam[i].vis[1])
ans+=sam[i].len-sam[sam[i].fa].len;
printf("%lld\n",ans);
}
signed main(){
// int t;scanf("%d",&t);
// while(t--)
solve();
return 0;
}
7.sam
#include<bits/stdc++.h>
using namespace std;
const int N=2000005;
char s[N];
int a[N],c[N],siz[N];
int last,cnt;
int ch[N<<1][26],fa[N<<1],len[N<<1];
void extend(int C)
{
int p=last,np=++cnt;
last=np;
len[np]=len[p]+1;
for(;p&&!ch[p][C];p=fa[p])ch[p][C]=np;
if(!p)fa[np]=1;
else
{
int q=ch[p][C];
if(len[p]+1==len[q])fa[np]=q;
else
{
int nq=++cnt;
len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for(;ch[p][C]==q;p=fa[p])ch[p][C]=nq;
}
}
siz[np]=1;
}
void build()
{
for(int i=1;i<=cnt;i++)c[len[i]]++;
for(int i=1;i<=cnt;i++)c[i]+=c[i-1];
for(int i=1;i<=cnt;i++)a[c[len[i]]--]=i;
for(int i=cnt;i;i--){int p=a[i];siz[fa[p]]+=siz[p];}
}
void solve()
{
long long ans=0;
for(int i=1;i<=cnt;i++)if(siz[i]!=1)
ans=max(ans,1ll*len[i]*siz[i]);
printf("%lld\n",ans);
}
int main()
{
scanf("%s",s+1);
int Len=strlen(s+1);
last=cnt=1;
for(int i=1;i<=Len;i++)extend(s[i]-'a');
build();
solve();
return 0;
}
// Template Ver.220713 - StelaYuri
//#pragma GCC optimize(3)
//#include<bits/stdc++.h>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<chrono>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<functional>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<random>
#include<set>
#include<sstream>
#include<stack>
#include<string>
#include<unordered_map>
#include<utility>
#include<vector>
using namespace std;
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
//using namespace __gnu_pbds;
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(auto i=(a);i<=(b);i++)
#define repp(i,a,b) for(auto i=(a);i<(b);i++)
#define per(i,a,b) for(auto i=(a);i>=(b);i--)
#define perr(i,a,b) for(auto i=(a);i>(b);i--)
#define REP(i,a,b,s) for(auto i=(a);i<=(b);i+=(s))
#define REPP(i,a,b,s) for(auto i=(a);i<(b);i+=(s))
#define PER(i,a,b,s) for(auto i=(a);i>=(b);i-=(s))
#define PERR(i,a,b,s) for(auto i=(a);i>(b);i-=(s))
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
#define YES cout<<"Yes\n"
#define NO cout<<"No\n"
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace BasicT {
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const int dx[8]={0,1,0,-1,1,1,-1,-1},dy[8]={1,0,-1,0,1,-1,1,-1};
const ll mod=998244353;
mt19937 mtrandom(std::chrono::system_clock::now().time_since_epoch().count());
template<typename T>T getRandom(T l,T r){return uniform_int_distribution<T>(l,r)(mtrandom);}
template<typename T>T gcd(T a,T b){return b==0?a:gcd(b,a%b);}
template<typename T>T qmul(T a,T b){T r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
template<typename T>T qpow(T a,T n){T r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
template<typename T>T qpow(T a,T n,T p){T r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}
}
namespace DebugT {
void debug(){cerr<<'\n';}template<typename T,typename... Args>void debug(T x,Args... args){cerr<<"[ "<<x<< " ] , ";debug(args...);}
template<typename Ta,typename Tb>istream& operator>>(istream &in,pair<Ta,Tb> &x){in>>x.first>>x.second;return in;}
template<typename Ta,typename Tb>ostream& operator<<(ostream &out,const pair<Ta,Tb> &x){out<<x.first<<' '<<x.second;return out;}
}
namespace FastIOT {
const int bsz=1<<18;char bf[bsz],*head,*tail;
inline char gc(){if(head==tail)tail=(head=bf)+fread(bf,1,bsz,stdin);if(head==tail)return 0;return *head++;}
template<typename T>inline void read(T &x){T f=1;x=0;char c=gc();for(;!isdigit(c);c=gc())if(c=='-')f=-1;for(;isdigit(c);c=gc())x=x*10+c-'0';x*=f;}
template<typename T>inline void print(T x){if(x<0)putchar(45),x=-x;if(x>9)print(x/10);putchar(x%10+48);}
template<typename T>inline void println(T x){print(x);putchar('\n');}
}
using namespace BasicT;
using namespace DebugT;
//using namespace FastIOT;
namespace SAM {
const int maxc=26;
const int maxn=1000050;
int n,
len[maxn<<1], //最长子串的长度 (该节点子串数量=len[x]-len[link[x]])
link[maxn<<1], //后缀链接(最短串前部减少一个字符所到达的状态)
cnt[maxn<<1], //被后缀连接的数
nex[maxn<<1][maxc], //状态转移(尾部加一个字符的下一个状态)
idx, //节点编号
last; //最后节点
long long epos[maxn<<1], //enpos数(该状态子串出现数量)
a[maxn]; //长度为i的子串出现最大次数
void init() {
last=idx=1; //root起始点
link[1]=len[1]=0;
}
//SAM建图
void Extend(int c) { //插入字符,为字符ascii码值
++n;
int x=++idx; //创建一个新节点x
len[x]=len[last]+1; //长度等于最后一个节点+1
epos[x]=1; //接受节点子串除后缀连接还需加一
int p; //第一个有C转移的节点
for(p=last;p&&!nex[p][c];p=link[p])nex[p][c]=x; //沿着后缀连接 将所有没有字符c转移的节点直接指向新节点
if(!p)link[x]=1,cnt[1]++; //全部都没有c的转移 直接将新节点后缀连接到起点
else{
int q=nex[p][c]; //p通过c转移到的节点
if(len[p]+1==len[q]) //pq是连续的
link[x]=q,cnt[q]++; //将新节点后缀连接指向q即可 q节点的被后缀连接数+1
else{
int nq=++idx; //不连续 需要复制一份q节点
len[nq]=len[p]+1; //令nq与p连续
link[nq]=link[q]; //因后面link[q]改变此处不加cnt
memcpy(nex[nq],nex[q],sizeof(nex[q])); //复制q的信息给nq
for(;p&&nex[p][c]==q;p=link[p])
nex[p][c]=nq; //沿着后缀连接 将所有通过c转移为q的改为nq
link[q]=link[x]=nq; //将x和q后缀连接改为nq
cnt[nq]+=2; //nq增加两个后缀连接
}
}
last=x; //更新最后处理的节点
}
void GetNpos() { //求npos数,即该节点子串出现次数
queue<int> q;
for(int i=1;i<=idx;i++)
if(!cnt[i])q.push(i); //将所有没被后缀连接指向的节点入队
while(!q.empty()){
int x=q.front(); q.pop();
epos[link[x]]+=epos[x]; //子串数量等于所有后缀连接指向该节点的子串数量和+是否为接受节点
if(--cnt[link[x]]==0)q.push(link[x]); //当所有后缀连接指向该节点的处理完毕后再入队
}
}
long long GetSubNum() { //求不相同子串数量
long long ans=0;
for(int i=2;i<=idx;i++)ans+=len[i]-len[link[i]]; //一状态子串数量等于len[i]-len[link[i]]
return ans;
}
void GetSubMax() { //求出所有长度为k的子串中出现次数最多的子串出现次数
GetNpos();
for(int i=1;i<=idx;i++)a[len[i]]=max(a[len[i]],epos[i]); //长度<=k的子串中出现次数最多的子串出现次数的最小值
for(int i=n-1;i>=1;i--)a[i]=max(a[i],a[i+1]); //求一遍后缀最大值就是答案
}
}
char str[1000050];
void solve()
{
SAM::init();
cin>>(str+1);
int len=strlen(str+1);
for(int i=1;i<=len;i++)
SAM::Extend(str[i]-'a');
SAM::GetSubMax();
ll ans=0;
for(int i=1;i<=len;i++)
if(SAM::a[i]>1)
ans=max(ans,1LL*i*SAM::a[i]);
cout<<ans<<'\n';
}
signed main()
{
closeSync;
//multiCase
{
solve();
}
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
const int N=200005; // 两倍总串长
int sam[N][26],link[N],len[N];
char s[N],ch[N];
int last,cnt;
int sg[N];
int dfs(int x)
{
int vis[26]={0};
if(~sg[x])
return sg[x];
for(int i=0; i<26; i++)
if(sam[x][i])
vis[dfs(sam[x][i])]=1;
for(int i=0; i<26; i++)
if(!vis[i])
return sg[x]=i;
return sg[x];
}
void init()
{
last=cnt=1;
memset(link,0,sizeof(link));
memset(sam,0,sizeof(sam));
}
void add(int c)
{
int p,cur=++cnt;
len[cur]=len[last]+1;
for(p=last; p && !sam[p][c]; p=link[p])
sam[p][c]=cur;
if(!p)
link[cur]=1;
else
{
int q=sam[p][c];
if(len[q]==len[p]+1)
link[cur]=q;
else
{
int cl=++cnt;
len[cl]=len[p]+1;
link[cl]=link[q];
memcpy(sam[cl], sam[q], sizeof(sam[q]));
while(p && sam[p][c]==q)
{
sam[p][c]=cl;
p=link[p];
}
link[cur]=link[q]=cl;
}
}
last=cur;
}
int main()
{
while(~scanf("%s", s+1))
{
memset(sg,-1,sizeof(sg));
int lenlen=strlen(s+1);
init();
for(int i=1; i<=lenlen; i++)
add(s[i]-'a');
int ans=0;
int n;
scanf("%d", &n);
for(int i=1; i<=n; i++)
{
scanf("%s", ch+1);
int len2=strlen(ch+1);
int p=1;
for(int j=1; j<=len2; j++)
p=sam[p][ch[j]-'a'];
ans^=dfs(p);
}
if(ans)
cout << "Alice" << '\n';
else
cout << "Bob" << '\n';
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10, M = N << 1;
int ch[M][26], len[M], fa[M], np = 1, tot = 1;
vector<int> g[M];
char s[N], t[N];
int now[M];
long long ans;
void extend(int c)
{
int p = np; np = ++tot;
len[np] = len[p] + 1;
while (p && !ch[p][c]) {
ch[p][c] = np;
p = fa[p];
}
if (!p) {
fa[np] = 1;
}
else {
int q = ch[p][c];
if (len[q] == len[p] + 1) {
fa[np] = q;
}
else {
int nq = ++tot;
len[nq] = len[p] + 1;
fa[nq] = fa[q], fa[q] = fa[np] = nq;
while (p && ch[p][c] == q) {
ch[p][c] = nq;
p = fa[p];
}
memcpy(ch[nq], ch[q], sizeof ch[q]);
}
}
}
void dfs(int u)
{
for (auto son : g[u]) {
dfs(son);
now[u] = max(now[u], now[son]);
}
ans += max(0, min(len[u], now[u]) - len[fa[u]]);
}
signed main()
{
scanf("%s%s", s, t);
for (int i = 0; s[i]; ++i) {
extend(s[i] - 'a');
}
for (int i = 2; i <= tot; ++i) {
g[fa[i]].emplace_back(i);
}
int p = 1, leng = 0;
for (int i = 0; t[i]; ++i) {
int c = t[i] - 'a';
while (p > 1 && !ch[p][c]) {
p = fa[p];
leng = len[p];
}
if (ch[p][c]) {
++leng;
p = ch[p][c];
}
now[p] = max(now[p], leng);
}
dfs(1);
printf("%lld\n", ans);
return 0;
}