思路:只枚举c1和c2,然后从上到下扫描各行。每次碰到一个新的行r,把c1,c2两列的内容作为一个二元组存到一个map中。如果map的键值中已经存在这个二元组,该二元组映射到的就是所要求的r1,而当前行就是r2。在主循环之前先做一个预处理——给所有字符串分配一个编号,则整个数据库中每个单元格都变成了整数,上述二元组就变成了两个整数,这个操作同样用到了map。
version 1(1440ms):
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 10000 + 5,maxm = 10 + 5;
typedef pair<int,int> P;
int m,n,table[maxn][maxm];
string readstr(){
string s;
s.resize(20); //一定要sesize 不然会报错 原因暂时不清楚 反正感觉就不太对。。。最低是20
int cnt = 0;
char c;
for(;;){
c = getchar();
if(c != '\n' && c != '\r') break;
}
for(;;){
if(c == ',' || c == '\n') break;
s[cnt++] = c;
c = getchar();
}
return s;
}
int main(){
while(scanf("%d %d",&n,&m) == 2){
memset(table,0,sizeof(table));
map<string,int>snum;
int cnt = 0;
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
string s = readstr();
if(!snum.count(s)) snum[s] = ++cnt;
table[i][j] = snum[s];
}
}
int mark = 0;
for(int c1 = 1;c1 <= m;c1++){
for(int c2 = c1+1;c2 <= m;c2++){
map<P,int>record;
for(int r = 1;r <= n;r++){
P t = make_pair(table[r][c1],table[r][c2]);
if(record.count(t)){
printf("NO\n%d %d\n%d %d\n",record[t],r,c1,c2);
mark = 1;
break;
}
record[t] = r;
}
if(mark) break;
}
if(mark) break;
}
if(!mark) printf("YES\n");
}
return 0;
}
version 2(1470ms,使用getline读取):
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 10000 + 5,maxm = 10 + 5;
typedef pair<int,int> P;
int m,n,table[maxn][maxm];
int main(){
while(scanf("%d %d",&n,&m) == 2){
getchar(); //一定要记得把这个换行符吃掉
memset(table,0,sizeof(table));
map<string,int>ID;
int cnt = 0;
string t,s;
for(int i = 1;i <= n;i++){
getline(cin,t);
int lastp = -1;
for(int j = 1;j <= m;j++){
int p = t.find(',',lastp+1);
if(p == string::npos) p = t.length();
s = t.substr(lastp+1,p-lastp-1);
if(!ID.count(s)) ID[s] = ++cnt;
table[i][j] = ID[s];
lastp = p;
}
}
int mark = 0;
for(int c1 = 1;c1 <= m && !mark;c1++){
for(int c2 = c1+1;c2 <= m && !mark;c2++){
map<P,int>record;
for(int r = 1;r <= n;r++){
P t = make_pair(table[r][c1],table[r][c2]);
if(record.count(t)){
printf("NO\n%d %d\n%d %d\n",record[t],r,c1,c2);
mark = 1;
break;
}
record[t] = r;
}
}
}
if(!mark) printf("YES\n");
}
return 0;
}