给定一个长度为n的字符串s,现在要从s中选出尽量多的子串,满足选出的子串都是回 文的,并且不存在一个串是另外一个串的子串的情况。
n ≤ 300000
题解:
建出PAM求这个DAG上的最长反链。
这道题的网络流复杂度是可以被卡满的,所以我也不知道这个数据范围是怎么回事,可能出题人有什么高妙做法?
原来以为PAM图上面最小链覆盖等于最小路径覆盖,但是并不。
反例:cabaccddabad
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int N=7e5+5;
int S,T;
namespace NetWork{
int n;
struct edge{
int to,cap,rev;
edge(int _to,int _cap,int _rev):to(_to),cap(_cap),rev(_rev){}
};
std::vector<edge> G[N];
typedef std::vector<edge>::iterator iter;
// iter cur[N];
inline void addedge(int u,int v,int val){
// cout<<u<<" "<<v<<"\n";
G[u].push_back(edge(v,val,G[v].size()));
G[v].push_back(edge(u,0,G[u].size()-1));
}
int lev[N],gap[N];
int dfs(int u,cs int &flow){
if(u==T)return flow;
int ans=0;
// cerr<<"u : "<<u<<" "<<cur[u]-G[u].begin()<<"\n";
for(iter e=G[u].end()-1;e!=G[u].begin()-1;--e)
if(e->cap&&lev[e->to]+1==lev[u]){
int delta=dfs(e->to,std::min(flow-ans,e->cap));
e->cap-=delta;
G[e->to][e->rev].cap+=delta;
ans+=delta;
if(ans==flow)return ans;
}
// cout<<u<<" to : this place "<<lev[u]<<" "<<gap[lev[u]]<<"\n";
if(0==--gap[lev[u]]){
lev[0]=0x3f3f3f3f;
// cout<<"!!!!\n";
// system("pause");
}
++gap[++lev[u]];
// cur[u]=G[u].begin();
return ans;
}
int ISAP(){
int mxflow=0;
// BFS();
memset(gap,0,sizeof gap);
memset(lev,0,sizeof lev);
gap[0]=n-2;
// for(int re i=1;i<=n;++i)cur[i]=G[i].begin();
while(lev[0]!=0x3f3f3f3f){
mxflow+=dfs(S,0x3f3f3f3f);
}
return mxflow;
}
}
char s[N];
int n;
namespace PAM{
int son[N][26],fa[N],len[N],now,last;
inline void init(){len[1]=-1,fa[0]=1;now=1;}
inline void push_back(char c,int i){c-='a';
int p=last;
while(s[i]!=s[i-len[p]-1])p=fa[p];
if(!son[p][c]){
len[++now]=len[p]+2;
int k=fa[p];
while(s[i]!=s[i-len[k]-1])k=fa[k];
fa[now]=son[k][c],son[p][c]=now;
}
last=son[p][c];
}
inline void solve(){
S=2*now+1,T=2*now+2;
for(int re i=2;i<=now;++i){
NetWork::addedge(S,i,1);
NetWork::addedge(i+now,T,1);
if(fa[i]>1){
NetWork::addedge(fa[i],i+now,1);
}
for(int re c=0;c<26;++c)if(son[i][c]){
NetWork::addedge(i,son[i][c]+now,1);
}
// NetWork::addedge(i+now,i,0x3f3f3f3f);
}
// cerr<<"???\n";
}
}
signed main(){
// freopen("country.in","r",stdin);freopen("country.out","w",stdout);
PAM::init();
scanf("%s",s+1);//double t=clock();
n=strlen(s+1);
for(int re i=1;i<=n;++i)PAM::push_back(s[i],i);
PAM::solve();
// cerr<<"???\n";
NetWork::n=PAM::now*2+2;
// cerr<<PAM::now<<"\n";
cout<<PAM::now-1-NetWork::ISAP()<<"\n";
return 0;
}