hdu 3746 kmp next求最小循环节

Given two sequences of numbers : a[1], a[2], …… , a[N], and b[1], b[2], …… , b[M] (1 <= M <= 10000, 1 <= N <= 1000000). Your task is to find a number K which make a[K] = b[1], a[K + 1] = b[2], …… , a[K + M - 1] = b[M]. If there are more than one K exist, output the smallest one.
Input
The first line of input is a number T which indicate the number of cases. Each case contains three lines. The first line is two numbers N and M (1 <= M <= 10000, 1 <= N <= 1000000). The second line contains N integers which indicate a[1], a[2], …… , a[N]. The third line contains M integers which indicate b[1], b[2], …… , b[M]. All integers are in the range of [-1000000, 1000000].
Output
For each test case, you should output one line which only contain K described above. If no such K exists, output -1 instead.
Sample Input
2
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 1 3
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 2 1
Sample Output
6
-1

让求出现两次以上的包含所有的循环节,求补足循环节的最小花费
这里我们说被匹配串是A 匹配串是B
next数组 是 B数组 前缀和后缀[i~m]的最大公共长度,所以后面所有的next 长度 指的都是前缀从0开始的。
所以 len-next[len] 必然是循环节长度,如果该长度len-next[len]!=0&&len%(len-next[len)==0 那么消耗就是0,如果不是完美的那么需要添加的字符数就是cir - (len-(len/cir)*cir)),相当与需要在最后一个循环节上面添加几个。 就是(循环节长度-最后已匹配的长度)%循环节长度

#include <bits/stdc++.h>
using namespace std;

const int maxn=100100 ;

int f[maxn]; 
void getfill(char *s,int len)  
{  
    memset(f,0,sizeof(f)); 
    for(int i=1;i<=len;i++)  
    {  
        int j=f[i];  
        while(j && s[i]!=s[j])  
            j=f[j];  
        f[i+1]=(s[i]==s[j])?j+1:0;  
    }  
}  

char s[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        scanf(" %s",s);
        int len=strlen(s);
        getfill(s,len);
        int length=len-f[len];
        if(len!=length&&len%length==0)
            printf("0\n");
        else{
            int add=length-f[len]%length;
            printf("%d\n",add );
        }
    }
    return 0;
}
posted @ 2017-09-19 21:18  黑码的博客  阅读(87)  评论(0编辑  收藏  举报