日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

@hdu - 3746@ Cyclic Nacklace

發布時間:2025/3/20 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 @hdu - 3746@ Cyclic Nacklace 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • @description@
  • @solution@
  • @code@
  • @details@

@description@

給你一個長度為 n 的由小寫字母組成的字符串,讓你在末尾增加盡量少的字母,使它變為循環串。

input
多組數據。第一行數據組數 T,T <= 100。
接下來 T 行,每行一個長度為 n 的字符串,n <= 100000。

output
對于每組數據,輸出最少的字母數。

sample input
3
aaa
abca
abcde
sample output
0
2
5

@solution@

【我只是來復習 KMP 的……】

如果長度為 n 的串 \(S\) 是一個循環節為 \(k\) 的循環串的前綴,那么我們可以將它補成循環節為 \(k\) 的循環串。
如果 \(S\) 是循環節為 \(k_1\) 與循環節為 \(k_2\) 兩個串的前綴,則 \(S\) 一定是循環節為 \(gcd(k_1, k_2)\) 串的前綴。
假如 \(k_1\)\(k_2\) 的倍數,則將 \(S\) 補成循環節為 \(k_2\) 的代價一定小于等于改成循環節為 \(k_1\) 的。
綜合以上性質,我們相當于是要求解以 \(S\) 為前綴的循環串的最小循環節。

然后可以證明,"\(S\) 是一個循環節為 \(k\) 的循環串的前綴" 與 "\(S\) 長度為 \(n-k\) 的后綴等于 \(S\) 長度為 \(n-k\) 的前綴" 等價,即它們互為充要條件。
所以我們就可以用 KMP 搞了。

注意兩種特殊情況:(1)\(S\) 本身是循環串(2)以 \(S\) 為前綴的循環串的最小循環節為 \(S\) 的長度。

@code@

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 100000; void GetFail(char *T, int *f) {int lenT = strlen(T);f[0] = -1, f[1] = 0;for(int i=2;i<=lenT;i++) {int j = f[i-1];while( j != -1 && T[j] != T[i-1] )j = f[j];f[i] = j + 1;} } char S[MAXN + 5]; int fail[MAXN + 5]; void solve() {scanf("%s", S); GetFail(S, fail);int lenS = strlen(S);if( fail[lenS] == 0 ) printf("%d\n", lenS);else if( lenS % (lenS - fail[lenS]) == 0 ) printf("%d\n", 0);else printf("%d\n", (lenS - fail[lenS]) - lenS%(lenS - fail[lenS])); } int main() {int T; scanf("%d", &T);for(int i=1;i<=T;i++) solve(); }

@details@

一開始寫得極其復雜……還討論了它最后循環串的循環節等各種稀奇古怪的東西……
幾個月不碰這個玩意兒基本快忘完了吧……

轉載于:https://www.cnblogs.com/Tiw-Air-OAO/p/10202036.html

總結

以上是生活随笔為你收集整理的@hdu - 3746@ Cyclic Nacklace的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。