159. 奶牛矩阵
题目链接:https://www.acwing.com/problem/content/description/161/
思路: 枚举列的长度求出行的循环节 找到最小的行的循环节 即矩阵的宽
然后再通过宽缩短每一行的字符串
对每一行的字符串做kmp求出列的最小循环节 即确定下来高
然后高×宽即可 注意只有是完美循环节的时候 循环节长度才一定是最小循环节的倍数
如 AAABAA 这种最小循环节是4 但是 循环节也可以是5
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e4+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define ull unsigned long long 7 #define pi pair<int,int> 8 #define fi first 9 #define sc second 10 #define pb push_back 11 12 13 char s[maxn][100]; 14 int st[100]; 15 int nxt[maxn]; 16 17 18 int main() 19 { 20 ios::sync_with_stdio(false); 21 cin.tie(0); 22 int n,m; 23 cin>>n>>m; 24 for(int i=1;i<=n;i++) 25 { 26 for(int j=1;j<=m;j++) 27 { 28 cin>>s[i][j]; 29 } 30 for(int j=1;j<=m;j++) 31 { 32 int f=0; 33 for(int k=j;k<=m;k+=j)// 偏移量到m可以保证枚举完 34 { 35 for(int u=1;u<=j&&u+k<=m;u++) 36 { 37 if(s[i][u]!=s[i][k+u]) 38 { 39 f=1; 40 break; 41 } 42 } 43 if(f) break; 44 } 45 if(f) st[j]=1; 46 } 47 } 48 49 50 int wide=0; 51 for(int i=1;i<=m;i++) 52 { 53 if(!st[i]) 54 { 55 wide=i; 56 break; 57 } 58 } 59 for(int i=1;i<=n;i++) s[i][wide+1]=0; 60 for(int i=2,j=0;i<=n;i++) 61 { 62 while(j&&strcmp(s[i]+1,s[j+1]+1)) j=nxt[j]; 63 if(!strcmp(s[i]+1,s[j+1]+1)) j++; 64 nxt[i]=j; 65 } 66 int hei=n-nxt[n]; 67 cout<<hei*wide<<'\n'; 68 69 70 71 72 73 }