luogu P2462 [SDOI2007]游戏
还没人用01BFS?
那我来一发题解。
初始建图:
方案一:枚举i,j,暴力判断
时间复杂度:O(n^2✖26),妥妥地爆炸
方案二:枚举i,➕或➖一个字母
时间复杂度:O(n*26),可以承受,但是要hush
跑最长路:
方案一:dp 时间复杂度:未知,但会爆
方案二:dijkstra 时间复杂度:O((n+m)logm)但是好像一般
方案三:SPFA没试过,应该可以水过
方案四:DFS+记忆化
优点:记录路径方便
缺点:栈空间小,可能要人工栈
方案五:BFS+记忆化
优点:可以用循环队列
缺点:记忆路径有点烦
可以上std了!
std:
#include<bits/stdc++.h>
using namespace std;
const int N=10005,M=105;
const int B=5000005;
struct nody{
int rank;
int len;
}k[N];
struct node{
int u;
int val;
int last;
}q[B];
char s[N][M];
int hav[N][30]={0};
int n=0,cnt=0;
int hed[N],tal[B],nxt[B];
int h=1,t=0;
int H=1,T=0;
int f[N];//f[i]表示到i当前最长路
int maxn=0,p=0;
int maxnnn=0,maxnn=0;
int Q[10000005]={0};
int hushh(int a[]){
int sum=0;
for(int i=1;i<=26;i++){
sum=(sum*108+a[i])%9982445;
}
return sum;
}
inline void addege(int x,int y){
//printf("%d %d\n",x,y);
cnt++;
tal[cnt]=y;
nxt[cnt]=hed[x];
hed[x]=cnt;
}
bool check(int x,int y){
for(int i=1;i<=26;i++){
if(hav[x][i]>hav[y][i]) return 0;
else if(hav[y][i]-hav[x][i]>1) return 0;
}
return 1;
}
inline void print(int x){
for(int i=0;i<strlen(s[x]);i++) printf("%c",s[x][i]);
printf("\n");
}
void dfs(int x){
if(x==-1) return;
dfs(q[x].last);
print(q[x].u);
}
bool cmp(nody x,nody y){
return x.len<y.len;
}
int main(){
//freopen("a.in","r",stdin);
while(~scanf("%s",s[n+1])){
n++;
for(int j=0;j<strlen(s[n]);j++) hav[n][s[n][j]-'a'+1]++;//记录
}
for(int i=1;i<=n;i++){
for(int j=1;j<=26;j++){
hav[i][j]++;
int esp=Q[hushh(hav[i])];
if(esp!=0) addege(i,esp);
hav[i][j]--;
if(hav[i][j]>0){
//cout << i << " " << j << endl;
hav[i][j]--;
esp=Q[hushh(hav[i])];
if(esp==0){hav[i][j]++;continue;
}
else addege(esp,i);
hav[i][j]++;
}
}
Q[hushh(hav[i])]=i;
}
//接下来:跑个最长路(还要记忆路径,费力!)
//由于边权是1,所以跑个01最短路(BFS)
//别慌,有SPJ!
for(int i=1;i<=n;i++){
f[i]=1;
t++;
T++;
q[t].last=-1;
q[t].u=i;
q[t].val=1;
}
while(h<=t){
node u=q[h];
h++;
if(u.val<f[u.u]) continue;
if(u.val>f[u.u]) f[u.u]=u.val;
for(int i=hed[u.u];i;i=nxt[i]){
node v;
v.u=tal[i];
v.last=h-1;
v.val=u.val+1;
if(u.val+1>f[v.u]){
f[v.u]=u.val+1;
t++;
q[t]=v;
}
}
}
for(int i=1;i<=n;i++){
if(f[i]>maxn){
maxn=f[i];
p=i;
}
}
for(int i=t;i>=1;i--){
if(q[i].val==maxn&&q[i].u==p){
p=i;
break;
}
}
printf("%d\n",maxn);
dfs(p);
return 0;
}