感谢 谢大,duoxida,zhsl ,教会了我几个训练赛当中没有想出来的题。

 

A Force Brute

题意:  没发现其水题本质啊..   给定 N个单词, 然后问最大循环次数. 

解法:   KMP  next数组的运用, 更详细的可以看这一篇总结 http://www.cnblogs.com/yefeng1627/archive/2013/04/28/3050027.html

这里就简要说下,  因为求next的过程是一个一个构造循环节的, (L+1)-next[L+1] 即为当前字符串的最小循环节长度, 而 L%( (L+1)-next[L+1] ) 表示目前 循环节构造了多少个,若为0则意味着构造满了一个循环.  而 L / ( (L+1) - next[L+1] )  表是目前已经构造了的循环节数量.  所以最终结果为   

  令 d = (L+1) - next[L+1] ,   则 ans  = L/d + (L%d != 0) 

若 next[L+1] = 1, 则代表整个串是 最小循环节. 其实发现可以不特殊处理的.

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<map>
#include<string>
#include<algorithm>
using namespace std;

const int N = (int)1e5+10;

char str[N*25], s[30];
int nxt[N], a[N], top, n;

map<string,int> mp;
int main(){
    int T;
    scanf("%d", &T); getchar();
    while( T-- ){
        gets(str);
        top = n = 0;
        mp.clear();    
        char *p = strtok( str, " " );
        while( p ){
            if( mp.count(p) == 0 )    mp[p] = ++top;    
            a[n++] = mp[p];
            p = strtok( NULL, " " );
        }
    //    for(int i = 0; i < n; i++)
    //        printf("%d ", a[i] ); puts("");
        int i = 0, j = 1; nxt[1] = 0;
        while( j <= n ){
            if( i == 0 || a[i-1] == a[j-1] )
                nxt[++j] = ++i;
            else    i = nxt[i];
        }
    //    for(int i = 1; i <= n+1; i++)
    //        printf("%d ", nxt[i] ); puts("");
        if( nxt[n+1] != 1 ){
            int d = (n+1)-nxt[n+1];
            printf("%d\n", n/d + (n%d!=0) );
        }     
        else puts("1");    
    }
    return 0;
}
View Code

相关文章:

  • 2021-08-19
  • 2021-11-17
  • 2022-12-23
  • 2021-05-31
  • 2021-08-23
  • 2021-12-08
  • 2021-11-10
  • 2021-07-09
猜你喜欢
  • 2021-07-19
  • 2022-02-20
  • 2021-10-23
  • 2021-11-03
  • 2022-01-21
  • 2021-11-10
  • 2021-12-07
相关资源
相似解决方案