• HDU 4333 Revolving Digits 扩张KMP


    标题来源:HDU 4333 Revolving Digits

    意甲冠军:求一个数字环路移动少于不同数量 等同 于的数字

    思路:扩展KMP求出S[i..j]等于S[0..j-i]的最长前缀 推断 next[i] 大于等于n就是同样 小于n推断S[next[i]]和S[next[i]+i]的大小

    next数组的含义就是S字符串以i開始的和S本身(以0開始)的最长公共前缀 把题目输入的复制一倍 然后直接推断next数组 比較大小即可了

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int maxn = 200010;
    int f[maxn];
    char a[maxn];
    
    void getFail(char* s)
    {
    	int n = strlen(s);
    	int p = 0, k = 1;
    	for(int i = 0; i+1 < n && s[i] == s[i+1]; i++)
    		p++;
    	f[0] = n;	
    	f[1] = p;
    	for(int i = 2; i < n/2; i++)
    	{
    		int p = f[k]+k-1;
    		int l = f[i-k];
    		if(i+l-1 < p)
    			f[i] = l;
    		else
    		{
    			int j = p-i+1;
    			if(j < 0)
    				j = 0;
    			while(i+j < n*2 && s[i+j] == s[j])
    				j++;
    			f[i] = j;
    			k = i;
    		}
    	}
    }
    int main()
    {
    	int cas = 1;
    	int T;
    	scanf("%d", &T);
    	while(T--)
    	{
    		scanf("%s", a);
    		int n = strlen(a);
    		for(int i = 0; i < n; i++)
    		{
    			a[i+n] = a[i];
    		}
    		a[2*n] = 0;
    		getFail(a);
    		int len;
    		for(len = 1; len <= n; len++)
    		{
    			if(f[len]+len >= n)
    			{
    				if(n%len)
    					len = n;
    				break;
    			}
    		}
    		int sum1 = 0, sum2 = 0, sum3 = 0;
    		for(int i = 0; i < len; i++)
    		{
    			if(f[i] >= n)
    				sum2++;
    			else if(a[i+f[i]] > a[f[i]])
    				sum3++;
    			else
    				sum1++;
    		}
    		printf("Case %d: %d %d %d
    ", cas++, sum1, sum2, sum3);
    	}
    	return 0;
    }


     

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    E. Paired Payment 题解(多维最短路)
    九峰与子序列 题解(dp+hash)
    魏迟燕的自走棋 题解(并查集+思维)
    unix学习资料
    Tomcat > Cannot create a server using the selected type
    myeclipse使用hibernate正向工程和逆向工程
    jira的破解
    jsp:useBean用法
    java一个多线程的经典例子
    head first系列PDF资源
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4793729.html
Copyright © 2020-2023  润新知