The stardate is 1983, and Princess Heidi is getting better at detecting the Death Stars. This time, two Rebel spies have yet again given Heidi two maps with the possible locations of the Death Star. Since she got rid of all double agents last time, she knows that both maps are correct, and indeed show the map of the solar system that contains the Death Star. However, this time the Empire has hidden the Death Star very well, and Heidi needs to find a place that appears on both maps in order to detect the Death Star.
The first map is an N × M grid, each cell of which shows some type of cosmic object that is present in the corresponding quadrant of space. The second map is an M × N grid. Heidi needs to align those two maps in such a way that they overlap over some M × M section in which all cosmic objects are identical. Help Heidi by identifying where such an M × M section lies within both maps.
The first line of the input contains two space-separated integers N and M (1 ≤ N ≤ 2000, 1 ≤ M ≤ 200, M ≤ N). The next N lines each contain M lower-case Latin characters (a-z), denoting the first map. Different characters correspond to different cosmic object types. The next M lines each contain N characters, describing the second map in the same format.
The only line of the output should contain two space-separated integers i and j, denoting that the section of size M × M in the first map that starts at the i-th row is equal to the section of the second map that starts at the j-th column. Rows and columns are numbered starting from 1.
If there are several possible ways to align the maps, Heidi will be satisfied with any of those. It is guaranteed that a solution exists.
10 5
somer
andom
noise
mayth
eforc
ebewi
thyou
hctwo
again
noise
somermayth
andomeforc
noiseebewi
againthyou
noisehctwo
4 6
The 5-by-5 grid for the first test case looks like this:
mayth
eforc
ebewi
thyou
hctwo
题目大意:
给一个n*m的字符矩阵
再给一个m*n的字符矩阵(n>=m)
要求找到一个第一个字符矩阵的一个m*m的子矩阵,使其在第二个m*n的矩阵中也出现过
方法:
先字符串hash,求得第一个矩阵中任意一列任意一短行宽为m的字符串的hash值,使其作为匹配串。
第二个矩阵的每一列的hash值作为主串,进行匹配。
若匹配成功则得到答案。
若失败,继续枚举第一个矩阵的下一行。
1 #include<iostream> 2 using namespace std; 3 #include<cstdio> 4 #include<cstring> 5 #include<map> 6 typedef unsigned long long ull; 7 char S[3000][300]; 8 char M[300][3000]; 9 ull hS[3000][300]; 10 ull hM[300][3000]; 11 ull seed = 13331; 12 ull tS[3000]; 13 ull p[30000]; 14 ull tM[3000]; 15 unsigned long long* Getnext(ull *p,int len_p){//p为模式串 16 unsigned long long *Next = new unsigned long long[len_p+10]; 17 Next[0] = -1; 18 int j = -1,i=0; 19 while(i < len_p){//自身与自身匹配 20 while(j != -1&&p[j]!=p[i])//移动匹配串 21 j = Next[j]; 22 j+=1; 23 Next[++i] = j; 24 } 25 return Next; 26 } 27 int Kmp(unsigned long long *s,unsigned long long *p,int len_s,int len_p){//s为主串,p为匹配串 28 unsigned long long *Next = Getnext(p,len_p);//求得Next数组 29 int j = 0;//j为匹配串匹配到的位置 30 for(int i=0;i < len_s;i++){ 31 while(j != -1 && s[i] != p[j]) 32 j = Next[j]; 33 j+=1; 34 if(j == len_p){//匹配串匹配完毕 35 return i+1-len_p; 36 j = Next[j];//j退回到Next[j] 37 } 38 } 39 delete []Next; 40 return -1; 41 } 42 int main(){ 43 int n,m; 44 p[0]=1; 45 memset(hS,0,sizeof(hS)); 46 memset(hM,0,sizeof(hM)); 47 for (int i=1;i<30000;i++){ 48 p[i]=p[i-1]*seed; 49 } 50 scanf("%d%d",&n,&m); 51 for(int i=1;i<=n;i++) 52 scanf("%s",S[i]+1); 53 for(int i=1;i<=m;i++) 54 scanf("%s",M[i]+1); 55 for(int i=1;i<=n;i++){ 56 for(int j=1;j<=m;j++){ 57 hS[i][j] = hS[i-1][j] * seed + S[i][j] - '0'; 58 } 59 } 60 for(int i=1;i<=n;i++){ 61 hM[0][i] = 0; 62 for(int j=1;j<=m;j++){ 63 hM[j][i] = hM[j-1][i]*seed + M[j][i] - '0'; 64 } 65 tM[i-1] = hM[m][i]; 66 } 67 int zans = 0; 68 int x,y; 69 for(int i=m;i<=n;i++){ 70 for(int j=1;j<=m;j++){ 71 tS[j] = hS[i][j] - hS[i-m][j]*p[m]; 72 } 73 for(int j=0;j<m;j++){ 74 tS[j] = tS[j+1]; 75 } 76 tS[m] = 0; 77 int ans=Kmp(tM,tS,n,m); 78 if(ans<0) 79 continue; 80 zans = 1; 81 x = i-m+1; 82 y = ans+1; 83 break; 84 } 85 printf("%d %d",x,y); 86 return 0; 87 }