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 }
View Code

 

posted @ 2021-04-21 23:50  canwinfor  阅读(79)  评论(0编辑  收藏  举报