OKR-Periods of Words

题目链接:https://ac.nowcoder.com/acm/contest/955/D

思路: 要求的是最大循环节  那么就是用i-最小的公共前后缀来得到

暴力的话就是 每次i的时候nxt[i] 都往回跳直到不能跳为止,但这样最坏可能会到n^2

考虑如何优化  每次前面跳的时候直接让 nxt[i] 变化到最小 那么后面跳的时候就不会跳冗余的路径

相当于每个点只跳一次

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e6+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];
14 int nxt[maxn];
15 
16 
17 int main()
18 {
19     ios::sync_with_stdio(false);
20     cin.tie(0);
21     int n;
22     cin>>n>>(s+1);
23     for(int i=2,j=0;i<=n;i++)
24     {
25         while(j&&s[i]!=s[j+1]) j=nxt[j];
26         if(s[i]==s[j+1]) j++;
27         nxt[i]=j;
28     }
29     ll ans=0;
30     for(int i=1;i<=n;i++)
31     {
32         while(nxt[nxt[i]]) nxt[i]=nxt[nxt[i]];
33         if(nxt[i]) ans+=i-nxt[i];
34     }
35     cout<<ans<<'\n';
36 
37 }
View Code

 

posted @ 2021-04-22 09:53  canwinfor  阅读(178)  评论(0)    收藏  举报