using
System;
using
System.Collections.Generic;
class
Program {
static
long
mod = 257;
static
long
r = 256;
static
long
dr = 1;
static
long
dc = 1;
static
long
power(
int
a,
int
n,
long
m)
{
if
(n == 0) {
return
1;
}
if
(n == 1) {
return
a % m;
}
long
pow = power(a, n / 2, m);
if
((n & 1) != 0) {
return
((a % m) * (pow % m) * (pow % m)) % m;
}
else
{
return
((pow % m) * (pow % m)) % m;
}
}
static
bool
check(List<List<
char
> > txt,
List<List<
char
> > pat,
long
r,
long
c)
{
for
(
long
i = 0; i < pat.Count; i++) {
for
(
long
j = 0; j < pat[0].Count; j++) {
if
(pat[(
int
)i][(
int
)j]
!= txt[(
int
)i + (
int
)r]
[(
int
)j + (
int
)c])
return
false
;
}
}
return
true
;
}
static
List<
long
> findHash(List<List<
char
> > mat,
long
row)
{
List<
long
> hash =
new
List<
long
>();
long
col = mat[0].Count;
for
(
long
i = 0; i < col; i++) {
long
h = 0;
for
(
long
j = 0; j < row; j++) {
h = ((h * r) % mod
+ mat[(
int
)j][(
int
)i] % mod)
% mod;
}
hash.Add(h);
}
return
hash;
}
static
void
colRollingHash(List<List<
char
> > txt,
List<
long
> t_hash,
long
row,
long
p_row)
{
for
(
long
i = 0; i < t_hash.Count; i++) {
t_hash[(
int
)i]
= (t_hash[(
int
)i] % mod
- ((txt[(
int
)row][(
int
)i] % mod)
* (dr % mod))
% mod)
% mod;
t_hash[(
int
)i]
= ((t_hash[(
int
)i] % mod) * (r % mod))
% mod;
t_hash[(
int
)i]
= (t_hash[(
int
)i] % mod
+ txt[(
int
)row + (
int
)p_row][(
int
)i]
% mod)
% mod;
}
}
static
void
rabinKarp(List<List<
char
> > txt,
List<List<
char
> > pat)
{
long
t_row = txt.Count;
long
t_col = txt[0].Count;
long
p_row = pat.Count;
long
p_col = pat[0].Count;
dr = power((
int
)r, (
int
)p_row - 1, mod);
dc = power((
int
)r, (
int
)p_col - 1, mod);
List<
long
> t_hash = findHash(
txt, p_row);
List<
long
> p_hash = findHash(
pat, p_row);
long
p_val = 0;
for
(
long
i = 0; i < p_col; i++) {
p_val = (p_val * r + p_hash[(
int
)i]) % mod;
}
for
(
long
i = 0; i <= (t_row - p_row); i++) {
long
t_val = 0;
for
(
long
j = 0; j < p_col; j++) {
t_val
= ((t_val * r) + t_hash[(
int
)j]) % mod;
}
for
(
long
j = 0; j <= (t_col - p_col); j++) {
if
(p_val == t_val) {
if
(check(txt, pat, i, j)) {
Console.WriteLine(i +
" "
+ j);
}
}
t_val = (t_val % mod
- ((t_hash[(
int
)j] % mod)
* (dc % mod))
% mod
+ mod)
% mod;
t_val = (t_val % mod * r % mod) % mod;
t_val = (t_val % mod + t_hash[(
int
)j] % mod)
% mod;
}
if
(i < t_row - p_row) {
colRollingHash(txt, t_hash, i, p_row);
}
}
}
public
static
void
Main()
{
List<List<
char
> > txt =
new
List<List<
char
> >{
new
List<
char
>{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
},
new
List<
char
>{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
},
new
List<
char
>{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
},
new
List<
char
>{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
},
new
List<
char
>{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
}
};
List<List<
char
> > pat =
new
List<List<
char
> >{
new
List<
char
>{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
},
new
List<
char
>{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
},
new
List<
char
>{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
},
new
List<
char
>{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
},
};
rabinKarp(txt, pat);
}
}