1. 程式人生 > >「UVA10298」 Power Strings(KMP

「UVA10298」 Power Strings(KMP

length 如果能 href uva -a 一個 png cin stream

題目描述

PDF

技術分享圖片

輸入輸出格式

輸入格式:

技術分享圖片

輸出格式:

技術分享圖片

輸入輸出樣例

輸入樣例#1: 復制
abcd
aaaa
ababab
.
輸出樣例#1: 復制
1
4
3

題解

Luogu的題解

這裏是對目前最高贊題解結論的證明。

結論:設字符串長度為$n$,最長相同前後綴的長度為$next[i]$,

如$n$%$(n-next[n])=0$,則答案為$n/(n-next[n])$,否則為$1$。

證明:

我們求$next$數組的時候,相當於每次把當前串這樣對齊了一下↓
技術分享圖片

而$next$求到$n$時,上面串的$n$對應的就是下面串的$next[n]$。

技術分享圖片

這時候的$n-nxt[n]$就是箭頭指向的綠色部分。

技術分享圖片

而上下兩串其實是一樣的,所以下面串的前$n-nxt[n]$格和上面串的前$n-nxt[n]$相同。

又因為兩串由藍色框住的部分匹配,所以下面的綠框對應的部分和綠框相同。

技術分享圖片

依此遞推,可以得到,**如果循環節多於一個**,以前$n-nxt[n]$個為循環節,是可以鋪滿整串的。而且因為$nxt[n]$是盡量大的,所以這樣得到的循環節長度為所有可能情況中最小的,也就是我們所求的。

而如果$n$%$(n-next[n])≠0$,可以認為之前的循環節匹配仍然可以進行,但是最後一個循環節被強行割掉了一些。

技術分享圖片

顯然這樣就怎麽都安排不上了。

所以如$n$%$(n-next[n])=0$,就能排上,答案為$n/(n-next[n])$,否則只能以自己為循環節,答案為$1$。

代碼實現的時候註意一下自己代碼中$n$的定義和$nxt$數組的定義什麽的。

還是放一下我的代碼叭qwq

 1 /*
 2     qwerta
 3     UVA10298 Power Strings
 4     Accepted
 5     代碼 C++,0.65KB
 6     提交時間 2018-10-12 17:59:53
 7     耗時/內存
 8     100ms, 0KB
 9 */
10 #include<iostream>
11
#include<cstdio> 12 using namespace std; 13 int nxt[1000003]; 14 int main() 15 { 16 //freopen("a.in","r",stdin); 17 while(1) 18 { 19 string s; 20 getline(cin,s);//讀入一整行,放進s 21 if(s.length()==1&&s[0]==.)break; 22 int lens=s.length(); 23 //kmp求next 24 int k=-1; 25 nxt[0]=-1; 26 for(register int i=1;i<lens;++i) 27 { 28 while(k!=-1&&s[i]!=s[k+1])k=nxt[k]; 29 if(s[i]==s[k+1])k++; 30 nxt[i]=k; 31 } 32 int n=lens-1; 33 if((n+1)%(n-nxt[n])==0)//如果能恰好排滿循環節 34 printf("%d\n",((n+1)/(n-nxt[n])));//輸出總長除以循環節長度 35 else printf("1\n");//否則輸出1 36 } 37 return 0; 38 }

吐槽:拿來做模擬題壓軸被吐槽是結論題......

明明前兩天才講過啊!(摔

「UVA10298」 Power Strings(KMP