zoukankan      html  css  js  c++  java
  • UVAlive 3026 KMP 最小循环节

    KMP算法:

    一:next数组:next[i]就是前面长度为i的字符串前缀和后缀相等的最大长度,也即索引为i的字符失配时的前缀函数。

    二:KMP模板

     1 /*
     2 pku3461(Oulipo), hdu1711(Number Sequence)
     3 这个模板 字符串是从0开始的
     4 Next数组是从1开始的
     5 */
     6 #include <iostream>
     7 #include <cstring>
     8 using namespace std;
     9 
    10 const int maxn = 1000002;
    11 int _next[maxn];
    12 char S[maxn], T[maxn];
    13 int slen, tlen;
    14 
    15 void getNext()
    16 {
    17     int j, k;
    18     j = 0; k = -1; _next[0] = -1;
    19     while(j < tlen)
    20         if(k == -1 || T[j] == T[k])
    21             _next[++j] = ++k;
    22         else
    23             k = _next[k];
    24 }
    25 
    26 /*
    27 }
    28 返回模式串T在主串S中首次出现的位置
    29 返回的位置是从0开始的。
    30 */
    31 int KMP_Index()
    32 {
    33     int i = 0, j = 0;
    34     getNext();
    35 
    36     while(i < slen && j < tlen)
    37     {
    38         if(j == -1 || S[i] == T[j])
    39         {
    40             i++; j++;
    41         }
    42         else
    43             j = _next[j];
    44     }
    45     if(j == tlen)
    46         return i - tlen;
    47     else
    48         return -1;
    49 }
    50 /*
    51 返回模式串在主串S中出现的次数
    52 */
    53 int KMP_Count()
    54 {
    55     int ans = 0;
    56     int i, j = 0;
    57     if(slen == 1 && tlen == 1)
    58     {
    59         if(S[0] == T[0])
    60             return 1;
    61         else
    62             return 0;
    63     }
    64     getNext();
    65     for(i = 0; i < slen; i++)
    66     {
    67         while(j > 0 && S[i] != T[j])
    68             j = _next[j];
    69         if(S[i] == T[j])
    70             j++;
    71         if(j == tlen)
    72         {
    73             ans++;
    74             j = _next[j];
    75         }
    76     }
    77     return ans;
    78 }
    79 int main()
    80 {
    81 
    82     int TT;
    83     int i, cc;
    84     cin>>TT;
    85     while(TT--)
    86     {
    87         cin>>S>>T;
    88         slen = strlen(S);
    89         tlen = strlen(T);
    90         cout<<"模式串T在主串S中首次出现的位置是: "<<KMP_Index()<<endl;
    91         cout<<"模式串T在主串S中出现的次数为: "<<KMP_Count()<<endl;
    92     }
    93     return 0;
    94 }
    View Code

    三:KMP最小循环节、循环周期:

    定理:假设S的长度为len,则S存在最小循环节,循环节的长度L为len-next[len],子串为S[0…len-next[len]-1]。

    (1)如果len可以被len - next[len]整除,则表明字符串S可以完全由循环节循环组成,循环周期T=len/L。

    (2)如果不能,说明还需要再添加几个字母才能补全。需要补的个数是循环个数L-len%L=L-(len-L)%L=L-next[len]%L,L=len-next[len]。

    学习博客 https://www.cnblogs.com/chenxiwenruo/p/3546457.html

          https://www.cnblogs.com/c-cloud/p/3224788.html

    循环节例题

    题目链接   https://vjudge.net/problem/UVALive-3026

    解析  每个前缀的最小循环节  KMP跑一边判断能不能整除就可以了

    AC代码

     1 #include <bits/stdc++.h>
     2 #define pb push_back
     3 #define mp make_pair
     4 #define F first
     5 #define S second
     6 #define all(a) (a).begin(), (a).end()
     7 #define fillchar(a, x) memset(a, x, sizeof(a))
     8 #define huan printf("
    ");
     9 using namespace std;
    10 typedef long long ll;
    11 const int maxn=1e6+10,inf=0x3f3f3f3f;
    12 const ll mod=1e9+7;
    13 char p[maxn];
    14 int f[maxn];
    15 int main()
    16 {
    17     int n,kase=0;
    18     while(scanf("%d",&n)==1&&n)
    19     {
    20         scanf("%s",p);
    21         f[0]=0,f[1]=0;
    22         for(int i=1;i<n;i++)
    23         {
    24             int j=f[i];
    25             while(j&&p[i]!=p[j]) j=f[j];
    26             f[i+1]=(p[i]==p[j]?j+1:0);
    27         }
    28         printf("Test case #%d
    ", ++kase);
    29         for(int i=2;i<=n;i++)
    30         {
    31             if(f[i]>0&&i%(i-f[i])==0)
    32                 printf("%d %d
    ",i,i/(i-f[i]));
    33         }
    34         huan;
    35     }
    36 }
  • 相关阅读:
    SharePoint中获取当前登录的用户名
    SharePoint 2013 图文开发系列之InfoPath入门
    在InfoPath中如何获取当前用户的信息(Profile)
    更新当前列并添加其他列
    poj3067 Japan
    poj2481 Cows
    poj1195 Mobile phones
    poj2299 Ultra-QuickSort
    lower_bound()和upper_bound
    hdu4339 Query
  • 原文地址:https://www.cnblogs.com/stranger-/p/9395397.html
Copyright © 2011-2022 走看看