D. Prefixes and Suffixes 解析(思維、字串、Z-Algo)

Codeforce 432 D. Prefixes and Suffixes 解析(思維、字串、Z-Algo)

今天我們來看看CF432D
題目連結

題目
略,請直接看原題。

前言

實際上自己根本沒實作過Z-Algo,感覺很抖。

想法

首先看到了後綴和前綴的關係,就感覺和KMP或者Z-Algo脫不了關係。稍微複習一下KMP和Z-Algo的DP計算的意義,發現了基本上就是Z-Algo存的資料的應用。
對於第一個問題:有幾個後綴等於前綴,這顯然就是赤裸裸的用Z-Algo的資料。
對於第二個問題:只要觀察到,對於一個長度為\(l\)的前綴(等於後綴),任何\(Z[i]\ge l\)都會對這個子字串造成貢獻,也因此只要維護一個\(Z[i]\)的後綴和即可輕鬆得到答案。

注意,一般來說\(Z[0]=0\),因此最後我們需要自己改成\(Z[0]=length\)

程式碼:

const int _n=1e5+10;
int t,n,Z[_n],LEN,ans[_n],cnt,c[_n];
string s;
main(void) {ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
  cin>>s;LEN=s.length();n=LEN;
  int L = 0, R = 0;
  for (int i = 1; i < LEN; i++) {
    if (i > R) {
      L = R = i;
      while (R < n && s[R-L] == s[R]) R++;
      Z[i] = R-L; R--;
    } else {
      int k = i-L;
      if (Z[k] < R-i+1) Z[i] = Z[k];
      else {
        L = i;
        while (R < n && s[R-L] == s[R]) R++;
        Z[i] = R-L; R--;
      }
    }
  }
  Z[0]=LEN;
  rep(i,0,LEN)if(Z[i] and Z[i]>=LEN-i)ans[Z[i]]++;
  rep(i,1,LEN+1)if(ans[i])cnt++;
  cout<<cnt<<'\n';cnt=0;
  rep(i,0,LEN)if(Z[i])c[Z[i]]++;
  vector<PII> p;per(i,1,LEN+1){
    cnt+=c[i];if(ans[i])p.pb({i,cnt});
  }per(i,0,SZ(p))cout<<p[i].fi<<' '<<p[i].se<<'\n';
  return 0;
}

標頭、模板請點Submission看
Submission

posted @ 2020-11-22 12:29  petjelinux  阅读(261)  评论(0编辑  收藏  举报