57分好不到错因求助!!!我实在没找到问题
查看原帖
57分好不到错因求助!!!我实在没找到问题
104308
Capitalism_Gao楼主2020/8/3 21:09

57分找不到错因求助!!!我实在没找到问题

我想的方法是Trie树+模拟(不想用拓扑啊)
大致思路:(57分应该都是这么写的)

我们开一个small数组(字典序小的排在前面)
small[i][j]==1:当前字母i字典序小于j
small[i][j]==-1:当前字母i字典序大于j
small[i][j]==0:当前字母i,j之间顺序为确定
当需要small[i][j]=1时,small[i][j]却已被赋值为-1
这时发生冲突,就判断为不可行

而且,我看提交记录里有很多人和我都是57分,都是错同样的4个点,和Expected答案的差异都一样

我就搞不懂

然后我下了数据点4(n=30000,每个单词长度都为10)

Expected 是4630,我是4685(相信57pts的人情况都和我一样)

然后我又试着把数据点4的n值缩小,发现了一个惊人的事实

当n<=1300时,都是对的;
当n=1400时,我的输出:1218; Expected:1216 当n=1500时,我的输出:1304; Expected:1302 当n=1600时,我的输出:1392; Expected:1390 当n=1700时,我的输出:1483; Expected:1481 当n=1800时,我的输出:1574; Expected:1571 当n=1900时,我的输出:1636; Expected:1632 当n=2000时,我的输出:1540; Expected:1536 当n=2100时,我的输出:1596; Expected:1589

反正我就很懵

有没有哪位大佬帮我找下错啊

我的评测记录

#include<bits/stdc++.h>
using namespace std;

const int maxn=3e5+5; 
int n,cnt,order[maxn][27],small[27][27],ans[30005];
string s[30005];
bool book[maxn],have[maxn][27];

inline void build(string s,int len){
	int u=0;
	for(int i=0;i<len;i++){
		int son=s[i]-'a'+1;
		if(!have[u][son]){
			have[u][son]=1;
			order[u][son]=++cnt;
		}
		u=order[u][son];
	}
	book[u]=1;
}

inline bool check(string s,int len){
	for(int i=0;i<=26;i++) for(int j=0;j<=26;j++) small[i][j]=0;
	
	int u=0;
	for(int i=0;i<len;i++){
		if(book[u]) return 0;
		int son=s[i]-'a'+1;
		for(int alpha=1;alpha<=26;alpha++){
			if(alpha!=son&&have[u][alpha]){
	//			printf("small[%d][%d]=%d\n",son,alpha,small[son][alpha]);
				if(small[son][alpha]==1) continue;
				if(small[son][alpha]==-1) return 0;
				if(small[son][alpha]==0){
					small[son][alpha]=1;
					small[alpha][son]=-1;
				}
	//			printf("  --->small[%d][%d]=%d\n",son,alpha,small[son][alpha]);
			}
		}
		u=order[u][son];
	}
	return 1;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		cin>>s[i]; 
		build(s[i],s[i].size());
	}
	int tot=0;
	for(int i=1;i<=n;i++){
		bool p=check(s[i],s[i].size());
		if(!p) continue;
		ans[++tot]=i; 
	}
	
	for(int i=1;i<=tot;i++){
		cout<<s[ans[i]]<<"\n";
	}printf("%d\n",tot);
	return 0;
} 

当然,如果你看不习惯这份代码

我这里还有另一位叫Darth_Che的大佬的57分代码。

Darth_Che的评测记录

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define maxn 500005
using namespace std;

int n,tri[maxn][26],vis[maxn],cnt,ans,ord[26][26],fir[maxn];
string s[maxn];

void insert(string s) {
	int rt=0,len=s.size()-1;
	rep(i,0,len) {
		int id=s[i]-'a';
		if(!tri[rt][id]) tri[rt][id]=++cnt;
		rt=tri[rt][id];
	}
	vis[rt]++;
}

bool check(string s) {
	int rt=0,len=s.size()-1;
	rep(i,0,len) {
		int id=s[i]-'a';
		if(i!=len&&vis[tri[rt][id]]) return 0;
		rep(j,0,25) {
			if(tri[rt][j]&&id!=j) {
//				cout<<id<<" "<<j<<" "<<ord[id][j]<<'\n';
				if(!ord[id][j]) {
					ord[id][j]=1;
					ord[j][id]=2;
				} else if(ord[id][j]==2) return 0;
			}
		}
		rt=tri[rt][id];
	}
	return 1;
}

int main() {
	ios::sync_with_stdio(false);
	cin>>n;
	rep(i,1,n) {
		cin>>s[i];
		insert(s[i]);
	}
//	cout<<'\n';
	rep(i,1,n) {
		memset(ord,0,sizeof(ord));
//		cout<<s[i]<<" | ";
//		cout<<check(s[i])<<" ";
//		cout<<'\n';
//		cout<<s[i]<<" ";
		if(check(s[i])) ans++,fir[i]=1;
	}
	cout<<ans<<'\n';
	rep(i,1,n) if(fir[i]) cout<<s[i]<<'\n';
	return 0;
}
2020/8/3 21:09
加载中...