CodeEff/ECCO huggingface dataset:
# Original solution
from collections import defaultdict

h, w, m = list(map(int, input().split()))

row_dict = defaultdict(int)
col_dict = defaultdict(int)
row_col_dict = defaultdict(list)
for _ in range(m):
    row, col = list(map(int, input().split()))
    row_dict[row] += 1
    col_dict[col] += 1
    row_col_dict[row].append(col)

max_row = max(row_dict.values())
max_col = max(col_dict.values())

max_rows = [k for k, v in list(row_dict.items()) if v == max_row]
max_cols = [k for k, v in list(col_dict.items()) if v == max_col]
ans = max_row + max_col - 1
flg = False
if ans < m:
    for row in max_rows:
        for col in max_cols:
            if not col in row_col_dict[row]:
                ans += 1
                flg = True
                break
        if flg:
            break

print(ans)


# Optimized solution
from collections import defaultdict

h, w, m = list(map(int, input().split()))

row_dict = defaultdict(int)
col_dict = defaultdict(int)
row_col_dict = defaultdict(set)
for _ in range(m):
    row, col = list(map(int, input().split()))
    row_dict[row] += 1
    col_dict[col] += 1
    row_col_dict[row].add(col)

max_row = max(row_dict.values())
max_col = max(col_dict.values())

max_rows = [k for k, v in list(row_dict.items()) if v == max_row]
max_cols = [k for k, v in list(col_dict.items()) if v == max_col]
ans = max_row + max_col - 1
flg = False
if ans < m:
    for row in max_rows:
        for col in max_cols:
            if not col in row_col_dict[row]:
                ans += 1
                flg = True
                break
        if flg:
            break

print(ans)
# Original solution
from collections import defaultdict

h, w, m = list(map(int, input().split()))

row_dict = defaultdict(int)
col_dict = defaultdict(int)
row_col_dict = defaultdict(set)
for _ in range(m):
    row, col = list(map(int, input().split()))
    row_dict[row] += 1
    col_dict[col] += 1
    row_col_dict[row].add(col)

max_row = max(row_dict.values())
max_col = max(col_dict.values())

max_rows = [k for k, v in list(row_dict.items()) if v == max_row]
max_cols = [k for k, v in list(col_dict.items()) if v == max_col]
ans = max_row + max_col - 1
flg = False
if ans < m:
    for row in max_rows:
        for col in max_cols:
            if not col in row_col_dict[row]:
                ans += 1
                flg = True
                break
        if flg:
            break

print(ans)


# Optimized solution
from collections import defaultdict

h, w, m = list(map(int, input().split()))

row_dict = defaultdict(int)
col_dict = defaultdict(int)
row_col_dict = defaultdict(set)
for _ in range(m):
    row, col = list(map(int, input().split()))
    row_dict[row] += 1
    col_dict[col] += 1
    row_col_dict[row].add(col)

max_row = max(row_dict.values())
max_col = max(col_dict.values())

max_rows = {k for k, v in list(row_dict.items()) if v == max_row}
max_cols = {k for k, v in list(col_dict.items()) if v == max_col}
ans = max_row + max_col - 1
flg = False
if ans < m:
    for row in max_rows:
        for col in max_cols:
            if not col in row_col_dict[row]:
                ans += 1
                flg = True
                break
        if flg:
            break

print(ans)
# Original solution
#import sys
#import numpy as np
import math
#from fractions import Fraction
import itertools
from collections import deque
from collections import Counter
import heapq
#from fractions  import gcd
#input=sys.stdin.readline
import bisect
h,w,m=list(map(int,input().split()))
l={}
u={}
hw=[list(map(int,input().split())) for _ in range(m)]
sl=set()
for i in range(m):
    hr,wr=hw[i]
    if hr-1 in u:
        u[hr-1]+=1
    else:
        u[hr-1]=1
    if wr-1 in l:
        l[wr-1]+=1
    else:
        l[wr-1]=1
    
    sl.add((hr-1)*w+(wr-1))
resl=0
resu=0
cl=[]
cu=[]
for i in l:
    if resl<l[i]:
        resl=l[i]
        cl=[i]
    elif resl==l[i]:
        cl.append(i)
for i in u:
    if resu<u[i]:
        resu=u[i]
        cu=[i]
    elif resu==u[i]:
        cu.append(i)
ans=0
for i in cu:
    for j in cl:
        if (i*w+j) in sl:
            res=l[j]+u[i]-1
        else:
            res=l[j]+u[i]
        ans=max(res,ans)
print(ans)

# Optimized solution
#import sys
#import numpy as np
import math
#from fractions import Fraction
import itertools
from collections import deque
from collections import Counter
import heapq
#from fractions  import gcd
#input=sys.stdin.readline
import bisect
h,w,m=list(map(int,input().split()))
l={}
u={}
hw=[list(map(int,input().split())) for _ in range(m)]
s=set()

for i in range(m):
    hr,wr=hw[i]
    if hr-1 in u:
        u[hr-1]+=1
    else:
        u[hr-1]=1
    if wr-1 in l:
        l[wr-1]+=1
    else:
        l[wr-1]=1
    s.add((hr-1)*w+wr-1)
resl=0
resu=0
cl=[]
cu=[]
for i in l:
    if resl<l[i]:
        resl=l[i]
        cl=[i]
    elif resl==l[i]:
        cl.append(i)
for i in u:
    if resu<u[i]:
        resu=u[i]
        cu=[i]
    elif resu==u[i]:
        cu.append(i)
ans=0
if resu==m or resl==m :
  print(m)
  exit()
if len(cu)*len(cl)>m:
    ans=resl+resu
else:
    for i in cu:
        for j in cl:
            if i*w+j in s:
                res=resl+resu-1
            else:
                res=resl+resu
            ans=max(res,ans)
print(ans)
# Original solution
H,W,M=list(map(int,input().split()))
height=[0]*H
width=[0]*W
#bomb=[0]*M
bset=set()
#for k in range(M):
    #bomb[k]=[0]*2
for j in range(M):
    h,w=list(map(int,input().split()))
    bset.add((h-1,w-1))
    #bomb[j][0]=h-1
    #bomb[j][1]=w-1
    height[h-1]+=1
    width[w-1]+=1
#print(bomb)
#print(height)
#print(width)
hmax=max(height)
wmax=max(width)
flag=0
for i in range(H):
    if height[i]==hmax:
        for h in range(W):
            if width[h]==wmax:
                if (i,h) not in bset:
                    flag=1
                    break
if flag==1:
    print((hmax+wmax))
else:
    print((hmax+wmax-1))

# Optimized solution
H,W,M=list(map(int,input().split()))
height=[0]*H
width=[0]*W
#bomb=[0]*M
bset=set()
#for k in range(M):
    #bomb[k]=[0]*2
for j in range(M):
    h,w=list(map(int,input().split()))
    bset.add((h-1,w-1))
    #bomb[j][0]=h-1
    #bomb[j][1]=w-1
    height[h-1]+=1
    width[w-1]+=1
#print(bomb)
#print(height)
#print(width)
hmax=max(height)
wmax=max(width)
hindex=0
windex=0
for i in range(H):
    if height[i]==hmax:
        #print(i)
        hindex+=1
for h in range(W):
    if width[h]==wmax:
        #print(h)
        windex+=1
kouho=hindex*windex
equalbomb=0
for p in bset:
    if height[p[0]]==hmax and width[p[1]]==wmax:
        #print(p)
        equalbomb+=1

if kouho==equalbomb:
    print((hmax+wmax-1))
else:
    print((hmax+wmax))
# Original solution
H, W, M = list(map(int, input().split()))

targets = []
n_target_h = [0] * H
n_target_w = [0] * W

h_max = 0
w_max = 0
for i in range(M):
    h, w = list(map(int, input().split()))
    targets.append((h, w))
    n_target_h[h - 1] += 1
    n_target_w[w - 1] += 1
    h_max = max(h_max, n_target_h[h - 1])
    w_max = max(w_max, n_target_w[w - 1])

bomb_h = [i + 1 for i, h in enumerate(n_target_h) if h == h_max]
bomb_w = [i + 1 for i, w in enumerate(n_target_w) if w == w_max]

ans = h_max + w_max - 1
for h in bomb_h:
    for w in bomb_w:
        if not (h, w) in targets:
            ans = h_max + w_max
            break
    else:
        continue
    break

print(ans)

# Optimized solution
H, W, M = list(map(int, input().split()))

targets = []
n_target_h = [0] * H
n_target_w = [0] * W

for i in range(M):
    h, w = list(map(int, input().split()))
    targets.append((h, w))
    n_target_h[h - 1] += 1
    n_target_w[w - 1] += 1

h_max = max(n_target_h)
w_max = max(n_target_w)

bomb_h = [i + 1 for i, h in enumerate(n_target_h) if h == h_max]
bomb_w = [i + 1 for i, w in enumerate(n_target_w) if w == w_max]

count = len(bomb_h) * len(bomb_w)
for target in targets:
    if (n_target_h[target[0] - 1] == h_max) and (n_target_w[target[1] - 1] == w_max):
        count -= 1

if count > 0:
    ans = h_max + w_max
else:
    ans = h_max + w_max - 1

print(ans)
# Original solution
from bisect import bisect_left
def main():
    h, w, m = list(map(int, input().split()))
    bombs = set()
    cnt_row, cnt_col = [0]*(h+1), [0]*(w+1)
    for _ in range(m):
        y, x = list(map(int, input().split()))
        cnt_row[y] += 1
        cnt_col[x] += 1
        bombs.add((y, x))
    ans = 0
    for y, x in bombs:
        ans = max(ans, cnt_row[y]+cnt_col[x]-1)
    col_indexs = [i for i in range(w+1)]
    col_indexs.sort(key=lambda x: cnt_col[x])
    cnt_col.sort()
    row_indexs = [i for i in range(h+1)]
    row_indexs.sort(key=lambda x: cnt_row[x])
    cnt_row.sort()
    for i, row_val in zip(reversed(row_indexs), reversed(cnt_row)):
        p = ans - row_val
        idx = bisect_left(cnt_col, p)
        for k in reversed(list(range(idx, w+1))):
            j = col_indexs[k]
            if (i, j) in bombs:
                continue
            if ans < row_val + cnt_col[k]:
                ans = row_val + cnt_col[k]
                break
    print(ans)

if __name__ == "__main__":
    main()

# Optimized solution
from bisect import bisect_left
def main():
    h, w, m = list(map(int, input().split()))
    bombs = set()
    cnt_row, cnt_col = [0]*(h+1), [0]*(w+1)
    for _ in range(m):
        y, x = list(map(int, input().split()))
        cnt_row[y] += 1
        cnt_col[x] += 1
        bombs.add((y, x))
    max_cnt_row = max(cnt_row)
    max_cnt_col = max(cnt_col)
    idx_row = []
    idx_col = []
    for i in range(h+1):
        if cnt_row[i] == max_cnt_row:
            idx_row.append(i)
    for j in range(w+1):
        if cnt_col[j] == max_cnt_col:
            idx_col.append(j)
    ans = max_cnt_row + max_cnt_col - 1
    for i in idx_row:
        for j in idx_col:
            if not (i, j) in bombs:
                ans = max_cnt_row + max_cnt_col
                break
    print(ans)

if __name__ == "__main__":
    main()
# Original solution
#!/usr/bin/env python3
import sys
from collections import deque, Counter
from heapq import heappop, heappush
from bisect import bisect_right
from itertools import accumulate

sys.setrecursionlimit(10**6)
INF = 10**12
m = 10**9 + 7

def main():
    H, W, M = list(map(int, input().split()))
    h = [0] * H
    w = [0] * W
    hw = set()
    for i in range(M):
        tmph, tmpw = [int(x)-1 for x in input().split()]
        h[tmph] += 1
        w[tmpw] += 1
        hw.add((tmph,tmpw))
    # 最大値より1だけ小さくなる物が候補
    HMAX = max(h)
    hcandidate = []
    for i in range(H):
        if h[i] >= HMAX-1:
            hcandidate.append(i)

    WMAX = max(w)
    wcandidate = []
    for i in range(W):
        if w[i] >= WMAX-1:
            wcandidate.append(i)

    ans = 0
    for i in hcandidate:
        for j in wcandidate:
            res = h[i]+w[j]
            if (i,j) in hw:
                res -= 1
            ans = max(ans, res)
    print(ans)

if __name__ == "__main__":
    main()

# Optimized solution
#!/usr/bin/env python3
import sys
from collections import deque, Counter
from heapq import heappop, heappush
from bisect import bisect_right
from itertools import accumulate

sys.setrecursionlimit(10**6)
INF = 10**12
m = 10**9 + 7

def main():
    H, W, M = list(map(int, input().split()))
    h = [0] * H
    w = [0] * W
    hw = set()
    for i in range(M):
        tmph, tmpw = [int(x)-1 for x in input().split()]
        h[tmph] += 1
        w[tmpw] += 1
        hw.add((tmph,tmpw))
    # 最大値より1だけ小さくなる物が候補
    HMAX = max(h)
    h0 = []
    for i in range(H):
        if h[i] == HMAX:
            h0.append(i)

    WMAX = max(w)
    w0 = []
    for i in range(W):
        if w[i] == WMAX:
            w0.append(i)

    ans = 0
    for i in h0:
        for j in w0:
            if (i,j) not in hw:
                print((HMAX+WMAX))
                exit()
    print((HMAX+WMAX-1))

if __name__ == "__main__":
    main()
# Original solution
## coding: UTF-8
#memo:重なっている位置に爆弾があるかないかで、1こ増減することが考えられる
#import numpy as np

H, W, M = list(map(int,input().split()))

tate = [0] * H
yoko = [0] * W


bomb = set()
for i in range(M):
    hi, wi = list(map(int,input().split()))
    tate[hi-1] += 1
    yoko[wi-1] += 1
    bomb.add((hi,wi))

#print(tate)
#print(yoko)
#print(bomb)
'''
tate_max = max(tate)
yoko_max = max(yoko)
index_tate = [i for i, v in enumerate(tate) if v == tate_max]
index_yoko = [i for i, v in enumerate(yoko) if v == yoko_max]
'''
tate_max = 0
index_tate = []
for i, v in enumerate(tate):
    if(tate_max < v):
        tate_max = v
        index_tate = [i]
    elif(tate_max == v):
        index_tate.append(i)
#print(tate_max, index_tate)

yoko_max = 0
index_yoko = []
for i, v in enumerate(yoko):
    if(yoko_max < v):
        yoko_max = v
        index_yoko = [i]
    elif(yoko_max == v):
        index_yoko.append(i)
#print(yoko_max, index_yoko)


#print(index_tate, index_yoko)

dammy = True
#1子でも「そこにない」ものがあれば、そのまま加算、そうでなければ、1こ引く
there_is = True
for i in index_tate:
    for j in index_yoko:
        #print(i+1, j+1)
        if((i+1, j+1) in bomb):
            dammy = True
        else:
            there_is = False

if(there_is):
    print((tate_max + yoko_max - 1))
else:
    print((tate_max + yoko_max))


        




'''
#tate_max = [i for i, v in enumerate(tate) if v == max(tate)]
np_list_tate = np.array(tate)
np_list_yoko = np.array(yoko)
tate_max = np_list_tate.argmax()
yoko_max = np_list_yoko.argmax()
print(tate_max, yoko_max)
'''

# Optimized solution
## coding: UTF-8
#memo:重なっている位置に爆弾があるかないかで、1こ増減することが考えられる
#import numpy as np

H, W, M = list(map(int,input().split()))

tate = [0] * H
yoko = [0] * W


bomb = set()
for i in range(M):
    hi, wi = list(map(int,input().split()))
    tate[hi-1] += 1
    yoko[wi-1] += 1
    bomb.add((hi,wi))
    

#print(tate)
#print(yoko)
#print(bomb)
'''
tate_max = max(tate)
yoko_max = max(yoko)
index_tate = [i for i, v in enumerate(tate) if v == tate_max]
index_yoko = [i for i, v in enumerate(yoko) if v == yoko_max]
'''
tate_max = 0
index_tate = []
for i, v in enumerate(tate):
    if(tate_max < v):
        tate_max = v
        index_tate = [i]
    elif(tate_max == v):
        index_tate.append(i)
#print(tate_max, index_tate)

yoko_max = 0
index_yoko = []
for i, v in enumerate(yoko):
    if(yoko_max < v):
        yoko_max = v
        index_yoko = [i]
    elif(yoko_max == v):
        index_yoko.append(i)
#print(yoko_max, index_yoko)


#print(index_tate, index_yoko)

dammy = True
#1子でも「そこにない」ものがあれば、そのまま加算、そうでなければ、1こ引く
there_is = True
flg = False
for i in index_tate:
    for j in index_yoko:
        #print(i+1, j+1)
        if((i+1, j+1) in bomb):
            dammy = True
        else:
            there_is = False
            flg = True
            break
    if flg:
        break

if(there_is):
    print((tate_max + yoko_max - 1))
else:
    print((tate_max + yoko_max))


        




'''
#tate_max = [i for i, v in enumerate(tate) if v == max(tate)]
np_list_tate = np.array(tate)
np_list_yoko = np.array(yoko)
tate_max = np_list_tate.argmax()
yoko_max = np_list_yoko.argmax()
print(tate_max, yoko_max)
'''
# Original solution
H, W, M = list(map(int, input().split()))
h_list = [0 for _ in range(H + 1)]
w_list = [0 for _ in range(W + 1)]
bomb = []
for _ in range(M):
    h, w = list(map(int, input().split()))
    h_list[h] += 1
    w_list[w] += 1
    bomb.append([h, w])
h_max = max(h_list)
w_max = max(w_list)
h_index = []
w_index = []
for i in range(H + 1):
    if h_list[i] == h_max:
        h_index.append(i)
for i in range(W + 1):
    if w_list[i] == w_max:
        w_index.append(i)
tmp = -1        
for h in h_index:
    for w in w_index:
        if [h, w] not in bomb:
            tmp = 0
            break
print((h_max + w_max + tmp))

# Optimized solution
H, W, M = list(map(int, input().split()))
h_list = [0 for _ in range(H + 1)]
w_list = [0 for _ in range(W + 1)]
bomb = set([])
for _ in range(M):
    h, w = list(map(int, input().split()))
    h_list[h] += 1
    w_list[w] += 1
    bomb.add((h, w))
h_max = max(h_list)
w_max = max(w_list)
h_index = []
w_index = []
for i in range(H + 1):
    if h_list[i] == h_max:
        h_index.append(i)
for i in range(W + 1):
    if w_list[i] == w_max:
        w_index.append(i)
tmp = -1        
for h in h_index:
    for w in w_index:
        if (h, w) not in bomb:
            tmp = 0
            break
print((h_max + w_max + tmp))
# Original solution
(h,w,m),*s=[[*list(map(int,i.split()))]for i in open(0)]
r,c=[0]*-~h,[0]*-~w
for x,y in s:
    r[x]+=1
    c[y]+=1
print(((R:=max(r))+(C:=max(c))-(r.count(R)*c.count(C)==sum(r[x]+c[y]==R+C for x,y in s))))


# Optimized solution
(h,w,m),*s=[[*list(map(int,i.split()))]for i in open(0)]
r,c=[0]*-~h,[0]*-~w
for x,y in s:
    r[x]+=1
    c[y]+=1
R,C=max(r),max(c)
print((R+C-(r.count(R)*c.count(C)==sum(r[x]+c[y]==R+C for x,y in s))))
# Original solution
import sys
import collections

sys.setrecursionlimit(10 ** 8)

input = sys.stdin.readline


def main():
    H, W, M = [int(x) for x in input().split()]
    HW = [[int(x) for x in input().split()] for _ in range(M)]

    x = set()

    hc = collections.Counter()
    wc = collections.Counter()

    for h, w in HW:
        hc[h] += 1
        wc[w] += 1
        x.add((h, w))

    ans = 0
    hcma = hc.most_common()[0][1]
    wcma = wc.most_common()[0][1]
    f = False
    for a in hc.most_common():
        if a[1] != hcma:
            break
        for b in wc.most_common():
            if b[1] != wcma:
                break
            if (a[0], b[0]) in x:
                ans = max(ans, hcma + wcma - 1)
            else:
                ans = max(ans, hcma + wcma)
                f = True
                break
        if f:
            break

    print(ans)


if __name__ == '__main__':
    main()


# Optimized solution
import sys
import collections

sys.setrecursionlimit(10 ** 8)

input = sys.stdin.readline


def main():
    H, W, M = [int(x) for x in input().split()]
    HW = [[int(x) for x in input().split()] for _ in range(M)]

    x = set()

    hc = collections.Counter()
    wc = collections.Counter()

    for h, w in HW:
        hc[h] += 1
        wc[w] += 1
        x.add((h, w))

    ans = 0
    hcma = hc.most_common()[0][1]
    wcma = wc.most_common()[0][1]
    f = False
    bost_common = wc.most_common()
    for a in hc.most_common():
        if a[1] != hcma:
            break
        for b in bost_common:
            if b[1] != wcma:
                break
            if (a[0], b[0]) in x:
                ans = max(ans, hcma + wcma - 1)
            else:
                ans = max(ans, hcma + wcma)
                f = True
                break
        if f:
            break

    print(ans)


if __name__ == '__main__':
    main()
# Original solution
import sys
def input(): return sys.stdin.readline().strip()

def main():
    H, W, M = list(map(int, input().split()))
    bomb = set()
    yoko = [0] * W
    tate = [0] * H
    for _ in range(M):
        h, w = list(map(int, input().split()))
        bomb.add((h-1, w-1))
        yoko[w - 1] += 1
        tate[h - 1] += 1

    idx_yoko = [(yoko[i], i) for i in range(W)]
    idx_tate = [(tate[i], i) for i in range(H)]
    idx_yoko.sort(reverse=True, key=lambda x: (x[0], x[1]))
    idx_tate.sort(reverse=True, key=lambda x: (x[0], x[1]))
    ans = 0
    for p in range(min(5000, W)):
        for q in range(min(5000, H)):
            yoko_bomb, idx_w = idx_yoko[p]
            tate_bomb, idx_h = idx_tate[q]
            get_bomb = yoko_bomb + tate_bomb
            if (idx_h, idx_w) in bomb: get_bomb -= 1
            ans = max(ans, get_bomb)
    print(ans)



if __name__ == "__main__":
    main()


# Optimized solution
import sys
def input(): return sys.stdin.readline().strip()

def main():
    H, W, M = list(map(int, input().split()))
    bomb = set()
    yoko = [0] * W
    tate = [0] * H
    for _ in range(M):
        h, w = list(map(int, input().split()))
        bomb.add((h-1, w-1))
        yoko[w - 1] += 1
        tate[h - 1] += 1

    idx_yoko = [(yoko[i], i) for i in range(W)]
    idx_tate = [(tate[i], i) for i in range(H)]
    idx_yoko.sort(reverse=True, key=lambda x: (x[0], x[1]))
    idx_tate.sort(reverse=True, key=lambda x: (x[0], x[1]))
    ans = 0

    yoko_bomb, idx_w = idx_yoko[0]
    tate_bomb_max = idx_tate[0][0]
    for tate_bomb, idx_h in idx_tate:
        if tate_bomb != tate_bomb_max: break
        if (idx_h, idx_w) not in bomb:
            print((yoko_bomb + tate_bomb))
            return

    tate_bomb, idx_h = idx_tate[0]
    yoko_bomb_max = idx_yoko[0][0]
    for yoko_bomb, idx_w in idx_yoko:
        if yoko_bomb != yoko_bomb_max: break
        if (idx_h, idx_w) not in bomb:
            print((yoko_bomb + tate_bomb))
            return

    print((yoko_bomb_max + tate_bomb_max - 1))
    

if __name__ == "__main__":
    main()
# Original solution
from collections import Counter
H, W, M = list(map(int, input().split()))
count_row = Counter()
count_col = Counter()
count_point = Counter()
for i in range(M):
    h, w = list(map(int, input().split()))
    count_row[h] += 1
    count_col[w] += 1
    count_point[(h, w)] += 1

max_h, max_count_row = count_row.most_common()[0]
max_w, max_count_col = count_col.most_common()[0]
row_iter = [(h, c) for h, c in count_row.most_common() if c == max_count_row]
col_iter = [(w, c) for w, c in count_col.most_common() if c == max_count_col]
ans = 0
for h, row_c in row_iter:
    for w, col_c in col_iter:
        ans = max(ans, row_c+col_c-count_point[(h, w)])
print(ans)


# Optimized solution
from collections import Counter
H, W, M = list(map(int, input().split()))
count_row = Counter()
count_col = Counter()
count_point = Counter()
for i in range(M):
    h, w = list(map(int, input().split()))
    count_row[h] += 1
    count_col[w] += 1
    count_point[(h, w)] += 1

max_h, max_count_row = count_row.most_common()[0]
max_w, max_count_col = count_col.most_common()[0]
row_iter = [h for h, c in count_row.most_common() if c == max_count_row]
col_iter = [w for w, c in count_col.most_common() if c == max_count_col]
ans = max_count_row + max_count_col - 1
flag = False
for h in row_iter:
    for w in col_iter:
        if count_point[(h, w)] == 1:
            continue
        ans += 1
        flag = True
        break
    if flag:
        break
print(ans)
# Original solution
import sys

H,W,M = list(map(int, input().split()))
grid = [[0 for _ in range(W)] for _ in range(H)]

hc = [0 for h in range(H)]
wc = [0 for w in range(W)]

for _ in range(M):
    h,w = list(map(int, input().split()))
    h-=1
    w-=1
    grid[h][w] = 1
    hc[h] += 1
    wc[w] += 1

hmax = max(hc)
wmax = max(wc)

htable = []
for h in range(H):
    if hc[h] == hmax:
        htable.append(h)

wtable = []
for w in range(W):
    if wc[w] == wmax:
        wtable.append(w)

# print(uw, uh)
#print(grid)
#print(wc, uw)
#print(hc, uh)

found = False
for h in htable:
    for w in wtable:
        if grid[h][w] == 0:
            print((hmax + wmax))
            sys.exit(0)

print((hmax + wmax - 1))

# Optimized solution
H,W,M = list(map(int, input().split()))
# grid = [[0 for _ in range(W)] for _ in range(H)]
bombs = set()

hc = [0 for h in range(H)]
wc = [0 for w in range(W)]

for _ in range(M):
    h,w = list(map(int, input().split()))
    h-=1
    w-=1
    bombs.add((h, w))
    hc[h] += 1
    wc[w] += 1

hmax = max(hc)
wmax = max(wc)

htable = []
for h in range(H):
    if hc[h] == hmax:
        htable.append(h)

wtable = []
for w in range(W):
    if wc[w] == wmax:
        wtable.append(w)

# print(uw, uh)
#print(grid)
#print(wc, uw)
#print(hc, uh)

found = False
for h in htable:
    for w in wtable:
        if (h,w) not in bombs:
            print((hmax + wmax))
            exit(0)

print((hmax + wmax - 1))