1. 程式人生 > >HDU 3746 Cyclic Nacklace(KMP:補齊迴圈節)

HDU 3746 Cyclic Nacklace(KMP:補齊迴圈節)

CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, without any surprise, there are only 99.9 yuan left. he is too distressed and thinking about how to tide over the last days. Being inspired by the entrepreneurial spirit of "HDU CakeMan", he wants to sell some little things to make money. Of course, this is not an easy task.

As Christmas is around the corner, Boys are busy in choosing christmas presents to send to their girlfriends. It is believed that chain bracelet is a good choice. However, Things are not always so simple, as is known to everyone, girl's fond of the colorful decoration to make bracelet appears vivid and lively, meanwhile they want to display their mature side as college students. after CC understands the girls demands, he intends to sell the chain bracelet called CharmBracelet. The CharmBracelet is made up with colorful pearls to show girls' lively, and the most important thing is that it must be connected by a cyclic chain which means the color of pearls are cyclic connected from the left to right. And the cyclic count must be more than one. If you connect the leftmost pearl and the rightmost pearl of such chain, you can make a CharmBracelet. Just like the pictrue below, this CharmBracelet's cycle is 9 and its cyclic count is 2:

此題補齊迴圈節的幾種判斷方法

如果f[m]=0那麼要補m個

如果m%f[m]==0那麼已經存在迴圈節

否則需要補齊: 

分析:

最小迴圈節長度是m-f[m],那麼還要補充m-m%f[m];
1 題目要求的是給定一個字串,問我們還需要新增幾個字元可以構成一個由n個迴圈節組成的字串。
2 可知我們應該先求出字串的最小迴圈節的長度:假設字串的長度為len,那麼最小的迴圈節就是cir = len-next[len] ;
如果有len%cir == 0,那麼這個字串就是已經是完美的字串,不用新增任何字元;
如果不是完美的那麼需要新增的字元數就是cir - (len-(len/cir)*cir)),相當與需要在最後一個迴圈節上面新增幾個。
3 如果cir = 1,說明字串只有一種字元例如“aaa” ;
 如果cir = m說明最小的迴圈節長度為m,那麼至少還需m個;
 如果m%cir == 0,說明已經不用添加了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXM=100000+100;
int f[MAXM],m;
char P[MAXM];
void getFail(char *P,int *f)
{
    f[0]=f[1]=0;
    for(int i=1;i<m;i++)
    {
        int j=f[i];
        while(j && P[i]!=P[j]) j=f[j];
        f[i+1]= (P[i]==P[j])?j+1:0;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",P);
        m=strlen(P);
        getFail(P,f);//求next陣列;
        if(f[m]==0)
        {
            printf("%d\n",m);
            continue;
        }//當f[m]=0時,輸出它的長度;
        if(m%(m-f[m])==0) printf("0\n");//如果存在迴圈節
        else
        {
            int len1=m-f[m];//
            printf("%d\n",len1-m%len1);
        }
    }
    return 0;
}