HDU 6740 kmp最小循环节

题意:
给一个无线循环小数的前几位,给n,m

选择其中一种出现在前几位的循环节方式(a个数),循环节的长度b

使得n*a-m*b最大

样例:

2 1

12.1212

输出 6 

选择2,2*1-1*1=1;

选择12,2*4-2*1=6;

选择21,2*3-2*1=4;

选择212,2*3-3*1=3;

选择1212,2*4-4*1=4;

思路:

将小数部分,倒过来,求每个点的最小循环节,kmp中i-next[i]代表最小循环节

当倒过来的小数部分,n*i-m*(i-next[i])中的最大就是答案

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define il inline
 5 #define it register int
 6 #define inf 0x3f3f3f3f
 7 #define lowbit(x) (x)&(-x)
 8 #define mem(a,b) memset(a,b,sizeof(a))
 9 #define mod 998244353
10 const int maxn=1e7+10;
11 ll n,m;
12 int nexts[maxn];
13 char s[maxn],s2[maxn];
14 int p2=0;
15 il void GetNext(int l){
16     int i=0;
17     int j=-1;
18     nexts[0]=-1;
19     while(i<l){
20         if(j==-1 || s2[i]==s2[j]){
21             i++;
22             j++;
23             nexts[i] = j;
24         }
25         else
26             j = nexts[j];
27     }
28     return;
29 }
30 int main(){
31     while(~scanf("%lld%lld",&n,&m)){
32         scanf("%s",s);
33         int l=strlen(s);p2=0;
34         int i;
35         for(i=0;i<l;i++){
36             if(s[i]=='.'){
37                 break;
38             }
39         }
40         for(int k=l-1;k>i;k--){
41             s2[p2++]=s[k];
42         }
43         GetNext(p2);
44         ll maxx=-1e18;
45         for(i=1;i<=p2;i++){
46             maxx=max(maxx,(ll)i*n-(ll)(i-nexts[i])*m);
47             //cout<<i<<" "<<(i-nexts[i])<<endl;
48         }
49         printf("%lld\n",maxx);
50     }
51     return 0;
52 }
View Code

 

kmp模板

 1 inline void getnext(char *ss){
 2     mem(ne,0);
 3     int l=strlen(ss);
 4     int i=0,j=-1;ne[0]=-1;
 5     while(i<l){
 6         if (j == -1 || ss[i] == ss[j])
 7         {
 8             i++;
 9             j++;
10             ne[i] = j;
11         }
12         else{
13             j = ne[j];
14         }
15     }
16     return;
17 }
18 inline int kmp(char *ss,char *s){
19     int l=strlen(s),ls=strlen(ss);
20     int i=0,j=0,ans=0;
21     while(i<l){
22         if(j==-1||s[i]==ss[j])
23         {
24             i++;
25             j++;
26         }
27         else
28             j=ne[j];
29         if(j==ls)
30         {
31             ans++;
32             j=ne[j];
33         }
34     }
35     return ans;
36 }
View Code

 待补全

模板

 1 int next[maxn];
 2 string str[maxn];
 3 void get_next(string s){
 4     memset(next,0,sizeof(next));
 5     int len=s.length();
 6     int i,j;
 7     j=next[0]=-1;
 8     i=0;
 9     while(i<len){
10         while(j!=-1&&s[i]!=s[j]) j=next[j];
11         next[++i]=++j;
12     }
13 }
14 bool kmp(string a,string b){
15     int lena=a.length();
16     int lenb=b.length();
17     get_next(b);
18     int i=0,j=0;
19     while(i<lena){
20         while(j!=-1&&a[i]!=b[j]) j=next[j];
21         i++,j++;
22         if(j>=lenb) return true;
23     }
24     return false;
25 }
View Code

 

posted @ 2020-02-27 18:56  ouluy  阅读(...)  评论(...编辑  收藏