http://poj.org/problem?id=1204
ac 自动机。。将关键字建树。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<set>
#include<cstdio>
using namespace std;
const int kAho_Corasick_Size_ = 1e5 + 8;
const int kAho_Corasick_Ascii_ = 65;
const int kDir[16] = { -1, 0, -1, 1, 0, 1, 1, 1, 1, 0, 1, -1, 0, -1, -1, -1};
class Ans_Node_ {
public:
int place, x, y;
char dir;
Ans_Node_ ( int x1, int x2, int x3, char x4 ) {
place = x1, x = x2, y = x3, dir = x4;
}
bool operator < ( const Ans_Node_ &a ) const {
return place < a.place;
}
};
class Aho_Corasick_ {
public:
class Node_ {
public:
int next[26];
int fail, sum, len;
} tree[kAho_Corasick_Size_];
int size;
//----------------------分界线
void fSet_() {//初始化
memset ( tree, 0, sizeof tree );
size = 1;
}
void fInsert_ ( char *s, int place ) { //字符串插入字典树
int now = 0;
for ( int i = 0; s[i]; i++ ) {
int c = s[i] - kAho_Corasick_Ascii_;
if ( !tree[now].next[c] )
tree[now].next[c] = size++;
now = tree[now].next[c];
}
tree[now].sum = place;
tree[now].len = strlen ( s );
}
void fBuild_Fail_() { //构造失配指针
std::queue<int>que;
que.push ( 0 );
tree[0].fail = -1;
while ( !que.empty() ) {
int temp = que.front();
que.pop();
for ( int i = 0; i < 26; i++ )
if ( tree[temp].next[i] ) {
if ( temp == 0 ) tree[tree[temp].next[i]].fail = 0;
else {
int p = tree[temp].fail;
while ( p != -1 ) {
if ( tree[p].next[i] ) {
tree[tree[temp].next[i]].fail = tree[p].next[i];
break;
}
p = tree[p].fail;
}
if ( p == -1 )
tree[tree[temp].next[i]].fail = 0;
}
que.push ( tree[temp].next[i] );
}
}
}
void fMatch_ ( char *s, int str_I, int str_J, char dir ) ;
};
Aho_Corasick_ Aho;
set<Ans_Node_>se;
char in[1008][1008];
void Aho_Corasick_::fMatch_ ( char *s, int str_I, int str_J, char dir ) {
int now = 0, n = strlen ( s );
for ( int i = 0; i < n; i++ ) {
int c = s[i] - kAho_Corasick_Ascii_;
if ( tree[now].next[c] )
now = tree[now].next[c];
else {
int p = tree[now].fail;
while ( p != -1 && tree[p].next[c] == 0 )
p = tree[p].fail;
if ( p == -1 ) now = 0;
else now = tree[p].next[c];
}
if ( tree[now].sum )
se.insert ( Ans_Node_ ( tree[now].sum, str_I + kDir[2 * ( dir - kAho_Corasick_Ascii_ )] * ( i - tree[now].len + 1 )
, str_J + kDir[2 * ( dir - kAho_Corasick_Ascii_ ) + 1] * ( i - tree[now].len + 1 ), dir ) );
}
}
int main() {
int n, m, t;
while ( cin >> n >> m >> t ) {
for ( int i = 0; i < n; i++ )
scanf ( "%s", in[i] );
Aho.fSet_();
char temp[1508];
for ( int i = 1; i <= t; i++ ) {
scanf ( "%s", temp );
Aho.fInsert_ ( temp, i );
}
Aho.fBuild_Fail_();
const int kInfor[8][8] = {
{n - 1, n - 1, 0, m - 1, 0, 0, 0, 0},
{n - 1, n - 1, 0, m - 1, 0, n - 1, 0, 0},
{0, n - 1, 0, 0, 0, 0, 0, 0},
{0, n - 1, 0, 0, 0, 0, 0, m - 1},
{0, 0, 0, m - 1, 0, 0, 0, 0},
{0, 0, 0, m - 1, 0, n - 1, m - 1, m - 1},
{0, n - 1, m - 1, m - 1, 0, 0, 0, 0},
{0, n - 1, m - 1, m - 1, n - 1, n - 1, 0, m - 1}
};
se.clear();
for ( int k = 0; k < 8; k++ )
for ( int kk = 0; kk < 2; kk++ )
for ( int i = kInfor[k][0 + kk * 4]; i <= kInfor[k][1 + kk * 4]; i++ )
for ( int j = kInfor[k][2 + kk * 4]; j <= kInfor[k][3 + kk * 4]; j++ ) {
int flag = 0;
for ( int ii = i, jj = j; ii < n && jj < m && ii >= 0 && jj >= 0; ii += kDir[2 * k], jj += kDir[2 * k + 1] )
temp[flag++] = in[ii][jj];
temp[flag] = 0;
Aho.fMatch_ ( temp, i, j, k + kAho_Corasick_Ascii_ );
}
for ( set<Ans_Node_>::iterator it = se.begin(); it != se.end(); it++ )
cout << ( *it ).x << ' ' << ( *it ).y << ' ' << ( *it ).dir << endl;
}
return 0;
}