今天杂题
jzoj 6071 不同的缩写
https://jzoj.net/senior/#main/show/6071
终于给我打出来了哈哈哈哈
序列自动机真是个好东西
判重不要用map(难打不说,还慢),trie真是个好东西
数组一定要开大,莫名WA等着你
good
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=305;
const int MAXM=MAXN*MAXN;
int n;
char name[MAXN][MAXN],st[MAXN];
int len[MAXN],sum;
int cnt,tot,head[MAXN],match[MAXM],ans[MAXN],isv[MAXM];
struct edge{
int to,next;
edge(){to=next=0;}
edge(int to,int next):to(to),next(next){}
}g[MAXM];
struct node{
string s;
int to[26];
node(){memset(to,0,sizeof(to));}
}p[MAXM];
struct sq_automaton{
int next[MAXN][26];
void build(int id){
for(int i=len[id];i>=0;i--){
for(int j=0;j<26;j++) if(!next[i][j]) next[i][j]=next[i+1][j];
if(i) next[i-1][name[id][i-1]-'a']=i;
}
}
void add(int u,int v){
g[++cnt]=edge(v,head[u]),head[u]=cnt;
}
void find(int id,int dep,int x,int y,int lim){
if(dep) add(id,y),++sum,p[y].s=string(st,st+dep);
if(dep==lim||sum==n) return ;
for(int i=0;i<26;i++){
if(!next[x][i]) continue;
st[dep]=i+'a';
if(!p[y].to[i]) p[y].to[i]=++tot,p[tot]=node();
find(id,dep+1,next[x][i],p[y].to[i],lim);
if(sum==n) return ;
}
}
}sq[MAXN];
bool dfs(int x,int id){
for(int i=head[x];i;i=g[i].next){
int y=g[i].to;
if(isv[y]==id) continue;
isv[y]=id;
if(!match[y]||dfs(match[y],id)){
match[y]=x,ans[x]=y;
return 1;
}
}
return 0;
}
bool check(int lim){
cnt=tot=0,p[0]=node();
memset(head,0,sizeof(head));
for(int i=1;i<=n;i++) sum=0,sq[i].find(i,0,0,0,min(lim,len[i]));
memset(isv,0,sizeof(isv)),memset(match,0,sizeof(match));
for(int i=1;i<=n;i++) if(!dfs(i,i)) return 0;
return 1;
}
int main(){
freopen("diff.in","r",stdin);
freopen("diff.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++){
scanf("%s",name[i]);
len[i]=strlen(name[i]);
sq[i].build(i);
}
int l=1,r=300;
while(l<r){
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
if(check(l)){
cout<<l;
for(int i=1;i<=n;i++) cout<<endl<<p[ans[i]].s;
}
else cout<<-1;
return 0;
}