字符串周期的问题

如果s1s2s3s4...sn = s3s4s5...sns1s2

那么说明s1=s2,s2=s3,s3=s4,s4=s5....

说明这个字符串是一个周期串。

 

更一般的情况是 s(i)s(i+1)...s(n)s(1)...s(i-1) = s(j)s(j+1)..s(n)s(1)...s(j-1)  i!=j

那么说明以i开始的字符串是一个周期串。

 

题目:给我们一个字符串,要我们求它的最小表示,输出从哪个位置开始, 如果有多个, 那么返回最大的位置。

首先,用最小表示法求得开始位置最小的,然后用kmp求得循环节,然后强行移到最后。

当然了,也可以求出字典序最小的出现了多少次。

比如hdu3374

要求字典序最小和字典序最大的表示出现了多少次。

  1 #pragma warning(disable:4996)
  2 #include <iostream>
  3 #include <stdio.h>
  4 #include <string.h>
  5 #include <math.h>
  6 #include <string>
  7 #include <vector>
  8 #include <queue>
  9 #include <set>
 10 #include <map>
 11 #include <algorithm>
 12 #include <functional>
 13 using namespace std;
 14 
 15 const int N = 1000000 + 10;
 16 char str[N];
 17 char tmp[N];
 18 int next[N];
 19 void getNext(char *str,int n)
 20 {
 21     int i = 0,j = -1;
 22     next[0] = -1;
 23     while(i<n)
 24     {
 25         if(j==-1||str[i]==str[j])
 26         {
 27             ++i;
 28             ++j;
 29             next[i] = j;
 30         }
 31         else
 32             j = next[j];
 33     }
 34 }
 35 
 36 int minimalRepresentation(char *str, int n)
 37 {
 38     int i = 0,j = 1, k = 0;
 39     while(i<n && j<n && k<n)
 40     {
 41         int t = str[(i+k)%n] - str[(j+k)%n] ;
 42         if(t == 0)
 43             k++;
 44         else
 45         {
 46             if(t>0)
 47                 i+=k+1;
 48             else 
 49                 j+=k+1;
 50             if(i==j)
 51                 j++;
 52             k = 0;
 53         }
 54     }
 55     return i < j ? i : j;
 56 }
 57 int maxRepresentation(char *str, int n)
 58 {
 59     int i = 0,j = 1, k = 0;
 60     while(i<n && j<n && k<n)
 61     {
 62         int t = str[(i+k)%n] - str[(j+k)%n] ;
 63         if(t == 0)
 64             k++;
 65         else
 66         {
 67             if(t>0)
 68                  j+=k+1;
 69             else 
 70                 i+=k+1;
 71                
 72             if(i==j)
 73                 j++;
 74             k = 0;
 75         }
 76     }
 77     return i < j ? i : j;
 78 }
 79 int solve(char *str, int n)
 80 {
 81     getNext(str,n);
 82     return n/(n-next[n]);//n-next[n] 是周期
 83 }
 84 int main()
 85 {
 86     int idx1,times1,idx2,times2,n;
 87     while(scanf("%s",str)!=EOF)
 88     {
 89         n = strlen(str);
 90         idx1 = minimalRepresentation(str,n);
 91         for(int i=0;i<n;++i)
 92             tmp[i] = str[(i+idx1)%n];
 93         times1 = solve(tmp,n);
 94         idx2 = maxRepresentation(str,n);
 95         for(int i=0;i<n;++i)
 96             tmp[i] = str[(i+idx2)%n];
 97         times2 = solve(tmp,n);
 98         printf("%d %d %d %d\n",idx1+1,times1,idx2+1,times2);
 99         
100     }
101     return 0;
102 }
View Code

 

转载于:https://www.cnblogs.com/justPassBy/p/4806246.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值