/* 特征值k=m-next[m]就是最小循环节的长度, m%k就是去末尾遗留长度 */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; char strs[10005][100]; int r,c,w,h,f[1050],nxt[10005];//r是行,c是列 void kmp_pre1(char *s){//求一行的nxt数组 int nxtt[1005]={}; int m=strlen(s); int i,j; i=0;j=nxtt[0]=-1; while(i<m){ while(j!=-1 && s[i]!=s[j]) j=nxtt[j]; nxtt[++i]=++j; } //把可行的长度都在f中+1 int tmp=m-nxtt[m],k=0; while(k+tmp<=m){ k+=tmp; f[k]++; } //剩下的串枚举一次开头就好 for(k=m%(m-nxtt[m]);k;k=nxtt[k]){ f[m-nxtt[k]]++; } } void kmp_pre2(){ memset(nxt,0,sizeof nxt); int i,j; i=0,j=nxt[0]=-1; while(i<r){ while(j!=-1 && strcmp(strs[i],strs[j])!=0) j=nxt[j]; nxt[++i]=++j; } } int main(){ while(scanf("%d%d",&r,&c)==2){ memset(f,0,sizeof f);//宽度为i的子串出现的次数 w=c,h=r; for(int i=0;i<r;i++){ scanf("%s",strs[i]); kmp_pre1(strs[i]); } for(int i=1;i<=c;i++)//找到矩阵最小宽度 if(f[i]==r){w=i;break;} for(int i=0;i<r;i++) strs[i][w]='